/*
This file is part of JOP, the Java Optimized Processor
see <http://www.jopdesign.com/>
Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Created on 22.04.2004
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package tal;
import joprt.RtThread;
import util.Dbg;
import util.Timer;
import com.jopdesign.sys.Const;
import com.jopdesign.sys.Native;
/**
* @author martin
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class Loop extends RtThread {
Alarm[] alarm;
static final int MEL_CNT = 8;
Alarm cold;
Alarm ort;
Alarm accu;
Alarm accuEmpty;
int mask;
boolean parOk;
boolean startSend;
int counter;
boolean ortPushButton;
int ortTimer;
static final int ORT_MASK = 0x100;
static final int ERASE_MASK = 0x200;
static final int LED_TIME_MS = 200;
static final int LED_ORT = 0x100;
static final int LED_ACCU = 0x200;
static final int LED_ACCU_EMPTY = 0x400;
static final int LED_BLINK = 0x800;
// accu threshholds in 0.1 V
static final int VBAT_MAINS = 140;
static final int VBAT_EMPTY = 110;
static final int VBAT_OFF = 105;
/**
* Call all 23 hours.
*/
static final int CALL_PERIOD_SEC = 23*3600;
/**
* Remove ort after 8 hours.
*/
static final int ORT_TIME_SEC = 8*3600;
/**
* Wait some time befor sending the Alarm.
* Perhaps it's a short one and we can transmit
* this in one call.
*/
static final int SEND_WAIT_MS = 1000;
/**
* @param prio
* @param us
*/
public Loop(int prio, int us) {
super(prio, us);
Timer.loop(); // start the clock
alarm = new Alarm[MEL_CNT];
for (int i=0; i<MEL_CNT; ++i) {
alarm[i] = new Alarm(Alarm.MB_OFF+i, Tal.par.time[i]);
}
mask = Tal.par.mask;
parOk = Tal.par.ok;
startSend = false;
counter = 0;
cold = new Alarm(Alarm.SB1_OFF+0, 0);
// set cold to ON_OFF_PEND
cold.setState(true);
cold.setState(false);
ort = new Alarm(Alarm.SB2_OFF+1, 0);
ortPushButton = false;
accu = new Alarm(Alarm.SB2_OFF+2, 0);
accuEmpty = new Alarm(Alarm.SB2_OFF+4, 0);
}
public void run() {
boolean changed = false;
int ledTimer = Timer.getTimeoutMs(LED_TIME_MS);
int transmitTimer = Timer.getSec()+CALL_PERIOD_SEC;
for (;;) {
changed = checkAlarm();
if (changed && Tal.modem != null) {
Tal.modem.startSend();
} else if (Timer.secTimeout(transmitTimer)) {
if (Tal.modem != null && Tal.modem.startSend()) {
// only reschedule the timer if startSend() was ok.
Dbg.wr("Time to send a message\n");
transmitTimer = Timer.getSec()+CALL_PERIOD_SEC;
}
}
if (Timer.timeout(ledTimer)) {
ledTimer = Timer.getTimeoutMs(200);
setLeds();
} else {
// it's placed here to not
// waste time slots
Timer.loop();
checkAccu();
checkOrt();
}
waitForNextPeriod();
}
}
/**
*
*/
private void setLeds() {
int i;
boolean state;
int led = 0;
++counter;
for (i=0; i<MEL_CNT; ++i) {
if (alarm[i].getLedPattern(counter)) {
led |= 1<<i;
}
}
if (ort.getLedPattern(counter)) led |= LED_ORT;
if (accu.getLedPattern(counter)) led |= LED_ACCU;
if (accuEmpty.getLedPattern(counter)) led |= LED_ACCU_EMPTY;
i = parOk ? counter&0x02 : counter &0x01;
led |= (i!=0) ? LED_BLINK : 0;
Native.wr(led, Const.IO_LED);
}
private boolean checkAlarm() {
int i;
int val = Native.rd(Const.IO_IN)^mask;
for (i=0; i<MEL_CNT; ++i) {
alarm[i].setState(((val>>i)&1)==1);
}
if ((val&ERASE_MASK)!=0) {
Tal.par.erase();
for (;;) {
// wait till reset and flash the LEDs
++i;
if ((i&0x0f)==0) {
Native.wr(0xfff, Const.IO_LED);
} else {
Native.wr(0, Const.IO_LED);
}
waitForNextPeriod();
}
}
return Alarm.isPending();
}
private void checkOrt() {
boolean val = (Native.rd(Const.IO_IN) & ORT_MASK)!=0;
boolean ortAlarm = ort.isOn();
if (val && !ortPushButton) {
// trigger on rising edge
if (ortAlarm) {
// switch off
ort.setState(false);
} else {
ort.setState(true);
ortTimer = Timer.getSec()+ORT_TIME_SEC;
}
} else {
// check for timeout
if (ortAlarm && Timer.secTimeout(ortTimer)) {
// reset ort alarm
Dbg.wr("auto reset of ort\n");
ort.setState(false);
}
}
// thats the delay for edge detection
ortPushButton = val;
}
/**
*
*/
private void checkAccu() {
int i;
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
if (i<VBAT_MAINS) {
accu.setState(true);
} else {
accu.setState(false);
accuEmpty.setState(false);
}
if (i<VBAT_EMPTY) accuEmpty.setState(true);
if (i<VBAT_OFF) {
Dbg.wr("switch off!!!\n");
// battery switch is !d31 of LED port
Native.wr(-1, Const.IO_LED);
// no return, probably switching on again!
for (;;) {
waitForNextPeriod();
}
}
}
}