/*
* Copyright (c) Martin Schoeberl, martin@jopdesign.com
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Martin Schoeberl
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
package ejip_old;
import util.Dbg;
import com.jopdesign.sys.Const;
import com.jopdesign.sys.Native;
/**
* a very SIMPLE HTML server class.
*/
public class Html {
public static String prot;
public static String end;
public static int[] val;
public static int[] tmp;
private static int hits;
private static int[] outVal;
private static int[] valArr;
public static int[] msg;
private static final int MAX_MSG = 80;
private static String text;
/**
* allocate buffers.
*/
public static void init() {
val = new int[5];
tmp = new int[1500];
msg = new int[MAX_MSG];
outVal = new int[1];
for (int i=0; i<MAX_MSG; ++i) msg[i] = ' ';
// hits = 17800; // 10.3.2003 auch jetzt bei ACEX
// hits = 18320; // 14.3.2003
// hits = 18750; // 20.3.2003
// hits = 19720; // 31.3.2003
// hits = 19990; // 10.4.2003
// hits = 22030; // 15.5.2003
// hits = 27472; // 22.7.2003
// hits = 30104; // 23.9.2003
// hits = 30390; // 1.10.2003
// hits = 30477; // 6.10.2003
// hits = 32914; // 13.2.2004
// hits = 37038; // 27.4.2004
// hits = 38175; // 13.7.2004
// hits = 38800; // 17.8.2004
hits = 39291; // 9.9.2004
hits = 0;
outVal[0] = 0;
Native.wr(outVal[0], Const.IO_OUT);
text =
/*
"<html><head></head><body>"+
"<h2>Hej Rasmus and DDM class</h2>"+
"<h3>Greetings from Vienna.</h3>"+
"<h3>Have fun,</h3>"+
"<h3>Martin</h3>"+
"</body></html>";
*/
/*
"<html><head></head><body><h2>BG 263</h2>"+
"Some Communication Statistics<p>"+
"sent packets #0<br>"+
"sent bytes #1<br>"+
"rcvd packets #2<br>"+
"rcvd bytes #3<br>"+
"wrong packets #4<br>"+
"</body></html>";
*/
"<html><head></head><body>"+
// "<h2>TAL TeleAlarm</h2>"+
"<h2><a href=\"http://www.jopdesign.com/\">JOP</a> Web Server on Altera Cyclone EP1C6</h2>"+
"Analog 1: !a1 mA<br>"+
"Analog 2: !a2 mA<br>"+
"Vbat: !a3 V<p>"+
"input 1: !i1<br>"+
"input 2: !i2<br>"+
"input 3: !i3<br>"+
"input 4: !i4<br>"+
"input 5: !i5<br>"+
"input 6: !i6<br>"+
"input 7: !i7<br>"+
"input 8: !i8<br>"+
"input 9: !i9<br>"+
"input 10: !i:<br>"+
"<form method=\"get\">"+
"output 1: !o1 <input type=\"checkbox\" name=\"o1\">set 1<br>"+
"output 2: !o2 <input type=\"checkbox\" name=\"o2\">set 2<br>"+
"output 3: !o3 <input type=\"checkbox\" name=\"o3\">set 3<br>"+
"output 4: !o4 <input type=\"checkbox\" name=\"o4\">set 4"+
"<p><input type=\"submit\" value=\"Set outputs\">"+
"</form>"+
"<p><sub>!ht</sub>"+
"</body></html>";
prot = "HTTP/1.0 200 OK\r\n\r\n";
end = "\r\n\r\n";
}
/**
* set value array
*/
public static void setValArray(int[] vals) {
valArr = vals;
}
public static void setOutValArray(int[] out) {
outVal = out;
}
private static int append(int[] buf, int pos, String str) {
int ret, len;
len = str.length();
for (ret=0; ret<len; ++ret) {
buf[pos+ret] = str.charAt(ret);
}
return ret;
}
private static int append(int[] buf, int pos, int[] str) {
int ret;
for (ret=0; ret<str.length; ++ret) {
buf[pos+ret] = str[ret];
}
return ret;
}
private static int[] getTemp() {
int i = Native.rd(Const.IO_ADC1);
// Dbg.intVal(i>>>16);
i &= 0xffff;
// Dbg.wr('T');
// Dbg.intVal(i);
i = (i-600)/17+27;
// Dbg.intVal(i);
if (i>99) i = 99;
if (i<0) {
i = -i;
val[0] = '-';
} else {
val[0] = ' ';
}
val[1] = '0'+i/10;
val[2] = '0'+i%10;
val[3] = ' ';
val[4] = ' ';
return val;
}
private static void setInt(int val, int[] buf) {
int i;
for (i=buf.length-1; i>=0; --i) {
buf[i] = val%10+'0';
val /= 10;
if (val==0) break;
}
--i;
for (; i>=0; --i) {
buf[i] = ' ';
}
}
private static int[] getAnalog(int channel) {
int i = 0;
if (channel==1) {
i = Native.rd(Const.IO_ADC1); // I = ADCout * 3.3 / (100 * (2^16-1))
i *= 100;
i /= 19859;
} else if (channel==2) {
i = Native.rd(Const.IO_ADC2);
i *= 100;
i /= 19859;
} else if (channel==3) {
i = Native.rd(Const.IO_ADC3); // U = 11 * ADCout * 3.3 / (2^16-1)
i *= 100;
i /= 18054;
}
// value is now in 1/10 mA or 1/10 V
// setInt(i, val);
/*
i += 100;
i /= 201;
*/
val[4] = ' ';
val[3] = '0'+i%10;
val[2] = '.';
i /= 10;
val[1] = '0'+i%10;
val[0] = '0'+i/10;
return val;
}
private static int[] getHit() {
int j;
for (j=0; j<5; ++j) {
val[j] = ' ';
}
val[0] = '0'+hits/10000%10;
val[1] = '0'+hits/1000%10;
val[2] = '0'+hits/100%10;
val[3] = '0'+hits/10%10;
val[4] = '0'+hits%10;
return val;
}
private static int[] getDigital() {
setInt(Native.rd(Const.IO_IN), val);
return val;
}
private static void setMsg(int[] buf, int pos) {
int i, j;
for (i=0; i<MAX_MSG; ++i) {
msg[i] = ' ';
}
// Dbg.wr('m');
// Dbg.wr(':');
for (i=0; i<MAX_MSG; ++i) {
j = buf[pos+i];
if (j==' ') break;
if (j=='+') j=' ';
msg[i] = j;
//Dbg.wr(j);
}
}
private static final int HTML_START = 0x90000; // start at first address (should be changed!)
private static int getChar(int pos) {
// data from Flash
// return Native.rdMem(HTML_START+pos);
// data from String
if (pos>=text.length()) return 0;
return text.charAt(pos);
}
public static int setText(int[] buf, int req_pos, int req_len, int ret_pos) {
int i, j, k;
//Dbg.wr('\n');
//Dbg.wr('h');
//Dbg.wr('t');
//Dbg.wr('m');
//Dbg.wr('l');
//Dbg.wr(':');
//Dbg.intVal(hits);
// copy request to 'byte' buffer
for (i=0; i<req_len; i+=4) {
j = buf[req_pos+(i>>2)];
tmp[i] = j>>>24;
tmp[i+1] = (j>>>16)&0xff;
tmp[i+2] = (j>>>8)&0xff;
tmp[i+3] = j&0xff;
}
Dbg.wr('\n');
for (i=0; i<req_len; ++i) Dbg.wr(tmp[i]);
int ret = 0;
if (tmp[0]!='G' || tmp[1]!='E') return 0;
k = tmp[5];
if (k=='T') { // request for 'Tal.class'
ret = setClassFile(tmp);
} else {
processRequest(tmp, 5);
ret += append(tmp, ret, prot);
if (k=='d') { // request for 'data.txt'
ret += setData(tmp, ret);
} else {
++hits;
for (i=0; i<1000; ++i) {
j = getChar(i);
if (j==0) break; // EOF reached
if (j=='!') {
++i;
j = getChar(i);
++i;
k = getChar(i);
ret += setSpecial(tmp, ret, j, k);
} else if (j=='#') {
++i;
j = getChar(i)-'0';
if (valArr!=null && j>=0 && j<valArr.length) {
ret += setVal(tmp, ret, valArr[j]);
}
} else {
tmp[ret] = j;
++ret;
}
}
}
ret += append(tmp, ret, end);
}
// copy replay to word buffer
/*
Dbg.wr('\n');
for (i=0; i<ret; ++i) Dbg.wr(tmp[i]);
Dbg.wr('\n');
*/
tmp[ret] = 0; // make shure last bytes are 0 for checksum
tmp[ret+1] = 0;
tmp[ret+2] = 0;
k = 0;
for (i=0; i<(ret+3)>>2; ++i) {
j = (tmp[k]<<24) + (tmp[k+1]<<16) +
(tmp[k+2]<<8) + tmp[k+3];
buf[ret_pos+i] = j;
k += 4;
}
return ret;
}
/**
* Handle one HTTP request.
*/
private static void processRequest(int[] buf, int pos) {
if (buf[pos+0]!='?') return; // nothing to do!
int i = pos+1;
if (buf[i]=='m') {
setMsg(buf, i+2);
} else { // set/reset outValuts
outVal[0] = 0;
for(; i<100; ++i) {
if (buf[i]=='o') {
++i;
int j = buf[i]-'1';
if (j>=0 && j<=3) {
outVal[0] |= 1<<j;
}
} else if (buf[i]=='\r') {
break;
}
}
Native.wr(outVal[0], Const.IO_OUT);
}
}
private static int setVal(int[] buf, int pos, int val) {
int j;
for (j=0; j<5; ++j) {
buf[pos+j] = ' ';
}
buf[pos+0] = '0'+val/1000000%10;
buf[pos+1] = '0'+val/100000%10;
buf[pos+2] = '0'+val/10000%10;
buf[pos+3] = '0'+val/1000%10;
buf[pos+4] = '0'+val/100%10;
buf[pos+5] = '0'+val/10%10;
buf[pos+6] = '0'+val%10;
return 7;
}
private static int setSpecial(int[] buf, int pos, int ch1, int ch2) {
int i, j;
if (ch1=='m') {
return append(buf, pos, msg);
} else if (ch1=='a') {
return append(buf, pos, getAnalog(ch2-'0'));
} else if (ch1=='t') {
return append(buf, pos, getTemp());
} else if (ch1=='h') {
return append(buf, pos, getHit());
} else if (ch1=='i') {
i = Native.rd(Const.IO_IN);
j = ch2-'1';
if ((i&(1<<j))!=0) {
return append(buf, pos, "on");
} else {
return append(buf, pos, "off");
}
} else if (ch1=='o') {
i = outVal[0];
j = ch2-'1';
if ((i&(1<<j))!=0) {
return append(buf, pos, "on");
} else {
return append(buf, pos, "off");
}
}
return 0;
}
private static int setData(int[] buf, int pos) {
int ret = 0;
ret += append(buf, pos+ret, getAnalog(1));
ret += append(buf, pos+ret, getAnalog(2));
ret += append(buf, pos+ret, getDigital());
buf[pos+ret] = ' '; ++ret;
ret += append(buf, pos+ret, getHit());
return ret;
}
private static final int APPL_START = 0x80000 + 0x30000; // start of class file
// load Applet Tal.class
private static int setClassFile(int[] buf) {
int ret = Native.rdMem(APPL_START)<<8;
ret += Native.rdMem(APPL_START+1);
for (int i=0; i<ret; ++i) {
buf[i] = Native.rdMem(APPL_START+2+i);
}
return ret;
}
}