/*
 * Copyright(C) Paul und Scherer (mct.de/mct.net)
 *
 * This example demonstrates how to...
 *
 *  ... use the ethernet module as simple
 *      http server (port #80).
 *
 *  ... read the RTC temperature sensor.
 */

#include <string.h>
#include "../usleep.h"
#include "net.h"

#define SN	(255L<<24|255L<<16|255L<<8|192)	// choose subnet mask
#define GW	(194L<<24| 64L<<16|159L<<8| 65)	//        gateway addr
#define IP	(194L<<24| 64L<<16|159L<<8| 77)	//        IP      addr
#define PN	80				//        port number (www http)

#define BS	8192				// buffer size
#define BSC	3				//  code
#define MSK	0x1fff				// pointer mask

#define RTC	0x9e				// RTC IIC bus address

/*
 * The html page to be sent on connect. XXXXXX
 * is a place holder for the temperature value.
 */
static char page[] =
	"<html>"
	"<head>"
	"<meta http-equiv=Refresh content=30>"		// auto
	"<meta http-equiv=Pragma content=no-cache>"	//  reload
	"<title>NET2106 WEB-Server</title>"
	"</head>"
	"<body bgcolor=red>"
	"<center>"
	"<p><font size=-1>This page is automagically reloaded every 30 seconds.</font></p>"
	"<h1><font color=white>NET2106 WEB-Server</font></h1>"
	"<h4><font color=white>Test page...</font></h4>"
	"<h3>Board temperature:</h3>"
	"<p><font size=7 color=yellow>XXXXXX&deg;C</font></p>"
	"<p><a href=http://www.mct.de target=_top>mct.de</a><br>"
	"<a href=http://www.mct.net target=_top>mct.net</a></p>"
	"</center>"
	"</body>"
	"</html>";

/*
 * Read the RTC temperature sensor.
 *
 * Return temperature string in the
 * form "+/-ddd.d".
 */
static char *
getts(void)
{
	static char s[7];			// temp. string
	signed char t[2];			// temp. (integral/fraction val)

	if (iic_start(RTC)
	 || iic_write("\xee", 1)		// start convert T cmd
	 || iic_start(RTC)
	 || iic_write("\xaa", 1)		// read temperature cmd
	 || iic_start(RTC|1)
	 || iic_read(t, 2)) puts("Reading temperature failed!"), abort();

	/*
	 * If the fraction value is non-zero the temperature is
	 * 0.5 degree higher. This means, the integral value is
	 * one degree higher, in case it is negative.
	 */
	sprintf(s, "%+4d.%d", t[1] && *t < 0? *t+1: *t, t[1]? 5: 0);
	return s;
}

/*
 * The ethernet module channel 0 is initialized in TCP server mode.
 *
 * On connect, the received data is ignored, the temperature sensor
 * read and the result copied into the html page. Then, the page is
 * sent, and the channel closed, until the next connection is made.
 *
 * Note: No timeout while waiting for status!
 */
int
main(void)
{
	#define WDS	(sizeof(page)-1)	// write data size
	#define UTX	(BS-(tw&MSK))		// upper part of Tx buffer

	char *p = strstr(page, "XXXXX");	// find temperature place holder

	iic_init();				// initialize IIC bus interface
	while (iic_start(NET)) ;		// wait for NET device ready

	/*
	 * Initialize NET device.
	 */
	net_wl(NET_SMR, SN);			// subnet mask
	net_wl(NET_GAR, GW);			// gateway addr
	net_wl(NET_SIPR, IP);			// IP      addr
	net_wb(NET_RMSR, BSC);			// Rx data mem size
	net_wb(NET_TMSR, BSC);			// Tx data mem size
	net_wb(NET_C0_CR, 1);			// sys_init cmd
	while (!(net_rb(NET_C0_ISR)&1)) ;	// wait for init_ok

	printf("\n"
	       "TCP server\n"
	       "----------\n\n"
	       "     Subnet mask : %3d.%3d.%3d.%3d\n"
	       " Gateway address : %3d.%3d.%3d.%3d\n"
	       "      IP address : %3d.%3d.%3d.%3d\n",
		net_rb(NET_SMR ), net_rb(NET_SMR +1), net_rb(NET_SMR +2), net_rb(NET_SMR +3),
		net_rb(NET_GAR ), net_rb(NET_GAR +1), net_rb(NET_GAR +2), net_rb(NET_GAR +3),
		net_rb(NET_SIPR), net_rb(NET_SIPR+1), net_rb(NET_SIPR+2), net_rb(NET_SIPR+3)
	);

	while (1) {
		long tw;				// Tx wptr

		/*
		 * Initialize socket.
		 */
		net_wb(NET_C0_SOPR, 1);			// sock_stream(TCP)
		net_ww(NET_C0_SPR, PN);			// port number
		net_wb(NET_C0_CR, 2);			// sock_init cmd
		while (!(net_rb(NET_C0_ISR)&2)) ;	// wait for sinit_ok
		net_wb(NET_C0_CR, 8);			// listen cmd

		printf("\nDisconnected, waiting for connection (port #%d)...\n", net_rw(NET_C0_SPR));

		while (!(net_rb(NET_C0_ISR)&4)) ;	// wait for established

		printf("Connected (%d.%d.%d.%d)",
			net_rb(NET_C0_DIR),
			net_rb(NET_C0_DIR+1),
			net_rb(NET_C0_DIR+2),
			net_rb(NET_C0_DIR+3)
		);

		if (p) strncpy(p, getts(), 6);		// copy temperature into page

		/*
		 * Read Tx write pointer (first read shadow register
		 * then delay min. 1.6us and read the real pointer).
		 */
		net_rb(NET_C0_STW_PR), usleep(2), tw = net_rl(NET_C0_TW_PR);

		/*
		 * Write WDS bytes from page to TXB starting
		 * from tw and wrap around at end of buffer.
		 */
		if ((tw&MSK)+WDS > BS) net_wn(NET_TXB+(tw&MSK), page, UTX), net_wn(NET_TXB, page+UTX, WDS-UTX);
		else net_wn(NET_TXB+(tw&MSK), page, WDS);

		net_wl(NET_C0_TW_PR, tw+WDS);		// update Tx wptr
		net_wb(NET_C0_CR, 0x20);		// send cmd
		while (!(net_rb(NET_C0_ISR)&0x20)) ;	// wait for send_ok

		printf(", data sent (%d).\n", (int)WDS);

		net_wb(NET_C0_CR, 0x10);		// close cmd
		while (!(net_rb(NET_C0_ISR)&8)) ;	// wait for closed
	}
}
