irom static io_error_t read_register(string_t *error_message, int address, int reg, int *value)
{
	uint8_t i2cbuffer[2];
	i2c_error_t error;

	i2cbuffer[0] = reg;

	if((error = i2c_send(address, 1, &i2cbuffer[0])) != i2c_error_ok)
	{
		if(error_message)
			i2c_error_format_string(error_message, error);

		return(io_error);
	}

	if((error = i2c_receive(address, 1, &i2cbuffer[1])) != i2c_error_ok)
	{
		if(error_message)
			i2c_error_format_string(error_message, error);

		return(io_error);
	}

	*value = i2cbuffer[1];

	return(io_ok);
}
irom static app_action_t application_function_i2c_write(const string_t *src, string_t *dst)
{
	i2c_error_t error;
	static uint8_t bytes[32];
	int current, out;

	for(current = 0; current < (int)sizeof(bytes); current++)
	{
		if(parse_int(current + 1, src, &out, 16) != parse_ok)
			break;

		bytes[current] = (uint8_t)(out & 0xff);
	}

	if((error = i2c_send(i2c_address, current, bytes)) != i2c_error_ok)
	{
		string_cat(dst, "i2c_write");
		i2c_error_format_string(dst, error);
		string_cat(dst, "\n");
		i2c_reset();
		return(app_action_error);
	}

	string_format(dst, "i2c_write: written %d bytes to %02x\n", current, i2c_address);

	return(app_action_normal);
}
irom static app_action_t application_function_i2c_write(application_parameters_t ap)
{
	uint16_t src_current, dst_current;
	i2c_error_t error;
	uint8_t bytes[32];

	for(src_current = 1, dst_current = 0;
			(src_current < ap.nargs) && (dst_current < sizeof(bytes));
			src_current++, dst_current++)
	{
		bytes[dst_current] = (uint8_t)strtoul((*ap.args)[src_current], 0, 16);
	}

	if((error = i2c_send(i2c_address, dst_current, bytes)) != i2c_error_ok)
	{
		i2c_error_format_string("i2c-write", error, ap.size, ap.dst);
		strlcat(ap.dst, "\n", ap.size);
		i2c_reset();
		return(app_action_error);
	}

	snprintf(ap.dst, ap.size, "i2c_write: written %u bytes to %02x\n", dst_current, i2c_address);

	return(app_action_normal);
}
irom static io_error_t clear_set_register(string_t *error_message, int address, int reg, int clearmask, int setmask)
{
	uint8_t i2cbuffer[2];
	i2c_error_t error;

	i2cbuffer[0] = reg;

	if((error = i2c_send(address, 1, &i2cbuffer[0])) != i2c_error_ok)
	{
		if(error_message)
			i2c_error_format_string(error_message, error);

		return(io_error);
	}

	if((error = i2c_receive(address, 1, &i2cbuffer[1])) != i2c_error_ok)
	{
		if(error_message)
			i2c_error_format_string(error_message, error);

		return(io_error);
	}

	i2cbuffer[1] &= ~clearmask;
	i2cbuffer[1] |= setmask;

	if((error = i2c_send(address, 2, &i2cbuffer[0])) != i2c_error_ok)
	{
		if(error_message)
			i2c_error_format_string(error_message, error);

		return(io_error);
	}

	return(io_ok);
}
irom static app_action_t application_function_i2c_reset(application_parameters_t ap)
{
	i2c_error_t error;

	if((error = i2c_reset()) != i2c_error_ok)
	{
		i2c_error_format_string("i2c-reset", error, ap.size, ap.dst);
		strlcat(ap.dst, "\n", ap.size);
		return(app_action_error);
	}

	snprintf(ap.dst, ap.size, "i2c_reset: ok\n");

	return(app_action_normal);
}
irom static app_action_t application_function_i2c_read(const string_t *src, string_t *dst)
{
	int size, current;
	i2c_error_t error;
	uint8_t bytes[32];
	uint32_t start, stop, clocks, spent;

	if(parse_int(1, src, &size, 0) != parse_ok)
	{
		string_cat(dst, "i2c-read: missing byte count\n");
		return(app_action_error);
	}

	if(size > (int)sizeof(bytes))
	{
		string_format(dst, "i2c-read: read max %d bytes\n", sizeof(bytes));
		return(app_action_error);
	}

	start = system_get_time();

	if((error = i2c_receive(i2c_address, size, bytes)) != i2c_error_ok)
	{
		string_cat(dst, "i2c_read");
		i2c_error_format_string(dst, error);
		string_cat(dst, "\n");
		i2c_reset();
		return(app_action_error);
	}

	stop = system_get_time();

	string_format(dst, "> i2c_read: read %d bytes from %02x:", size, i2c_address);

	for(current = 0; current < size; current++)
		string_format(dst, " %02x", bytes[current]);

	string_cat(dst, "\n");

	clocks = (size + 1) * 20U;
	spent = (stop - start) * 1000U;

	string_format(dst, "> transferred %u bytes in %u scl clocks\n", size + 1U, clocks);
	string_format(dst, "> time spent: %u microseconds, makes %u kHz i2c bus\n",
			spent / 1000U, 1000000U / (spent / clocks));

	return(app_action_normal);
}
irom static app_action_t application_function_i2c_reset(const string_t *src, string_t *dst)
{
	i2c_error_t error;

	if((error = i2c_reset()) != i2c_error_ok)
	{
		string_cat(dst, "i2c-reset: ");
		i2c_error_format_string(dst, error);
		string_cat(dst, "\n");
		return(app_action_error);
	}

	string_cat(dst, "i2c_reset: ok\n");

	return(app_action_normal);
}
irom static io_error_t write_register(string_t *error_message, int address, int reg, int value)
{
	uint8_t i2cbuffer[2];
	i2c_error_t error;

	i2cbuffer[0] = reg;
	i2cbuffer[1] = value;

	if((error = i2c_send(address, 2, &i2cbuffer[0])) != i2c_error_ok)
	{
		if(error_message)
			i2c_error_format_string(error_message, error);

		return(io_error);
	}

	return(io_ok);
}
irom static app_action_t application_function_i2c_read(application_parameters_t ap)
{
	uint16_t length, current, size;
	i2c_error_t error;
	uint8_t bytes[32];

	size = atoi((*ap.args)[1]);

	if(size > sizeof(bytes))
	{
		snprintf(ap.dst, ap.size, "i2c-read: read max %u bytes\n", sizeof(bytes));
		return(app_action_error);
	}

	if((error = i2c_receive(i2c_address, size, bytes)) != i2c_error_ok)
	{
		i2c_error_format_string("i2c-read", error, ap.size, ap.dst);
		strlcat(ap.dst, "\n", ap.size);
		i2c_reset();
		return(app_action_error);
	}

	length = snprintf(ap.dst, ap.size, "i2c_read: read %u bytes from %02x:", size, i2c_address);
	ap.dst += length;
	ap.size -= length;

	for(current = 0; current < size; current++)
	{
		length = snprintf(ap.dst, ap.size, " %02x", bytes[current]);
		ap.dst += length;
		ap.size -= length;
	}

	snprintf(ap.dst, ap.size, "\n");

	return(app_action_normal);
}
irom static app_action_t application_function_i2c_read(const string_t *src, string_t *dst)
{
	int size, current;
	i2c_error_t error;
	uint8_t bytes[32];

	if(parse_int(1, src, &size, 0) != parse_ok)
	{
		string_cat(dst, "i2c-read: missing byte count\n");
		return(app_action_error);
	}

	if(size > (int)sizeof(bytes))
	{
		string_format(dst, "i2c-read: read max %d bytes\n", sizeof(bytes));
		return(app_action_error);
	}

	if((error = i2c_receive(i2c_address, size, bytes)) != i2c_error_ok)
	{
		string_cat(dst, "i2c_read");
		i2c_error_format_string(dst, error);
		string_cat(dst, "\n");
		i2c_reset();
		return(app_action_error);
	}

	string_format(dst, "i2c_read: read %d bytes from %02x:", size, i2c_address);

	for(current = 0; current < size; current++)
		string_format(dst, " %02x", bytes[current]);

	string_cat(dst, "\n");

	return(app_action_normal);
}