Files
epics-base/src/tools/makeBaseApp
Marty Kraimer 0c19e23835 added new rules
1996-09-04 15:29:48 +00:00

830 lines
20 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
#
# iocMakeApp
#
# Author: Marty Kraimer
#
#set -xv
SAVEDIR=$PWD
EXAMPLES=""
Cleanup() {
cd $SAVEDIR
rtncode=$1
shift 1
for MESSAGE
do
echo "$MESSAGE"
done
exit $rtncode
}
USAGE="Usage: iocMakeApp -r release -e appname ... "
if [ "$PWD" = "$HOME" ]; then Cleanup 1 "In Home Directory" "$USAGE"; fi;
#look for options (Currently only -r release and -e)
RELEASE=
while getopts r:e OPT
do
case $OPT in
r) RELEASE=$OPTARG
;;
e) EXAMPLES=TRUE
;;
\?)
Cleanup 1 "$USAGE"
;;
esac
done
shift `expr $OPTIND - 1`
#if user did not specify release and none exists error
if [ -z "$RELEASE" -a ! -f EPICS_BASE ]; then
Cleanup 1 "No release " "$USAGE"
fi
if [ ! -z "$RELEASE" ]; then
${RELEASE}/bin/${HOST_ARCH}/getrel ${RELEASE}
if [ ! -f EPICS_BASE ]; then
Cleanup 1 "Did not detect successful getrel" "$USAGE"
fi
fi
EPICS_BASE=`sed -e "s%EPICS_BASE=%%" < EPICS_BASE`
if [ ! -f Makefile ]; then
cat > Makefile <<-\END
TOP = .
include $(TOP)/config/CONFIG_APP
#add directories as follows
#DIRS += <dir>
include $(EPICS_BASE)/config/RULES_TOP
END
fi
if [ ! -d config ]; then
mkdir config
cat > config/CONFIG <<-\END
# Add any changes to make rules here
END
cat > config/CONFIG_APP <<-\END
#CONFIG_APP DO NOT EDIT THIS FILE
include $(TOP)/EPICS_BASE
include $(EPICS_BASE)/config/CONFIG
include $(TOP)/config/CONFIG
END
cat > config/RULES.Unix <<-\END
include $(EPICS_BASE)/config/RULES.Unix
END
cat > config/RULES.Vx <<-\END
include $(EPICS_BASE)/config/RULES.Vx
END
cat > config/RULES_DIRS <<-\END
include $(EPICS_BASE)/config/RULES_DIRS
END
fi
if [ $# = 0 ]; then Cleanup 0; fi;
for APPNAME
do
if [ -d "${APPNAME}" ]; then continue; fi
mkdir ${APPNAME}
if [ $? -ne 0 ]; then Cleanup 1 "$USAGE"; fi
cd ${APPNAME}
cat > Makefile <<-\END
TOP = ..
include $(TOP)/config/CONFIG_APP
DIRS = src
include $(EPICS_BASE)/config/RULES_DIRS
END
mkdir db
if [ -n "${EXAMPLES}" ]; then
#if source starts with blank tab replace by tab
sed -e "s/ / /" > db/dbExample.db <<-\END
record(ai, "$(user):aiExample")
{
field(DESC, "Analog input")
field(INP, "$(user):calcExample.VAL NPP NMS")
field(EGUF, "10")
field(EGU, "Counts")
field(HOPR, "10")
field(LOPR, "0")
field(HIHI, "8")
field(HIGH, "6")
field(LOW, "4")
field(LOLO, "2")
field(HHSV, "MAJOR")
field(HSV, "MINOR")
field(LSV, "MINOR")
field(LLSV, "MAJOR")
}
record(calc, "$(user):calcExample")
{
field(DESC, "Counter")
field(SCAN,"1 second")
field(FLNK, "$(user):aiExample")
field(CALC, "(A<B)?(A+C):D")
field(INPA, "$(user):calcExample.VAL NPP NMS")
field(INPB, "9")
field(INPC, "1")
field(INPD, "0")
field(EGU, "Counts")
field(HOPR, "10")
field(HIHI, "8")
field(HIGH, "6")
field(LOW, "4")
field(LOLO, "2")
field(HHSV, "MAJOR")
field(HSV, "MINOR")
field(LSV, "MINOR")
field(LLSV, "MAJOR")
}
record(xxx, "$(user):xxxExample")
{
field(DESC, "xxx record")
field(FLNK, "mrkc0a1.VAL ")
field(EGU, "Counts")
field(HOPR, "10")
field(HIHI, "8")
field(HIGH, "6")
field(LOW, "4")
field(LOLO, "2")
field(HHSV, "MAJOR")
field(HSV, "MINOR")
field(LSV, "MINOR")
field(LLSV, "MAJOR")
}
END
fi
mkdir src
cat > src/Makefile <<-\END
TOP=../..
include $(TOP)/config/CONFIG_APP
include $(EPICS_BASE)/config/RULES_ARCHS
END
sed -e "s/APPNAME/${APPNAME}/" > src/Makefile.Vx <<-\END
# Makefile.Vx
TOP = ../../..
include $(TOP)/config/CONFIG_APP
INSTALL_LOCATION = $(TOP)
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
END
if [ -n "${EXAMPLES}" ]; then
sed -e "s/APPNAME/${APPNAME}/" >> src/Makefile.Vx <<-\END
RECTYPES += xxxRecord.h
USR_INCLUDES += -I$(EPICS_BASE)/include
USER_DBDFLAGS += -I .. -I $(EPICS_BASE)/dbd
DBDEXPAND = APPNAMEInclude.dbd
DBDNAME = APPNAME.dbd
include ../baseLIBOBJS
LIBOBJS += xxxRecord.o
LIBOBJS += devXxxSoft.o
LIBOBJS += sncExample.o
LIBNAME = APPNAMESupport
SCRIPTS += st.APPNAME
SCRIPTS += vxWorks vxWorks.sym iocCore seq
END
else
sed -e "s/APPNAME/${APPNAME}/" >> src/Makefile.Vx <<-\END
#RECTYPES += xxxRecord.h
USR_INCLUDES += -I$(EPICS_BASE)/include
USER_DBDFLAGS += -I .. -I $(EPICS_BASE)/dbd
#DBDEXPAND = APPNAMEInclude.dbd
#DBDNAME = APPNAME.dbd
#include ../baseLIBOBJS
#LIBOBJS += xxx.o
#LIBNAME = APPNAMESupport
#SCRIPTS += st.APPNAME
#SCRIPTS += vxWorks vxWorks.sym iocCore seq
END
fi
sed -e "s/APPNAME/${APPNAME}/" >> src/Makefile.Vx <<-\END
include $(TOP)/config/RULES.Vx
#----------------------------------------
# ADD RULES AFTER THIS LINE
$(LIBNAME): ../baseLIBOBJS
$(DBDNAME): ../base.dbd ../APPNAMEInclude.dbd
$(DBDNAME): $(RECTYPES:%.h=%.dbd)
END
cat > src/Makefile.Unix <<-\END
# Makefile.Unix
TOP = ../../..
include $(TOP)/config/CONFIG_APP
INSTALL_LOCATION = $(TOP)
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#USR_CFLAGS +=
USR_INCLUDES += -I$(EPICS_BASE)/include
DEPLIBS += $(EPICS_BASE_LIB)/libca.a
DEPLIBS += $(EPICS_BASE_LIB)/libCom.a
USR_LDFLAGS = -L$(EPICS_BASE_LIB)
USR_LDLIBS = -lca -lDb -lCom
END
if [ -n "${EXAMPLES}" ]; then
sed -e "s/APPNAME/${APPNAME}/" >> src/Makefile.Unix <<-\END
OBJS += caExample.o
PROD += caExample
END
else
sed -e "s/APPNAME/${APPNAME}/" >> src/Makefile.Unix <<-\END
#OBJS += xxx.o
#PROD += xxx
END
fi
sed -e "s/APPNAME/${APPNAME}/" >> src/Makefile.Unix <<-\END
include $(TOP)/config/RULES.Unix
#----------------------------------------
# ADD RULES AFTER THIS LINE
END
if [ -n "${EXAMPLES}" ]; then
cat > src/${APPNAME}Include.dbd <<-\END
include "base.dbd"
include "xxxRecord.dbd"
device(xxx,CONSTANT,devXxxSoft,"SoftChannel")
END
else
cat > src/${APPNAME}Include.dbd <<-\END
include "base.dbd"
#private database definitions go here
#device(xxx,CONSTANT,devXxxSoft,"SoftChannel")
END
fi
cp ${EPICS_BASE}/dbd/base.dbd src/base.dbd
cp ${EPICS_BASE}/dbd/baseLIBOBJS src/baseLIBOBJS
sed -e "s/USER/${USER}/" \
-e "s/APPNAME/${APPNAME}/" > src/st.${APPNAME} <<-\END
# Example vxWorks startup file
#Following must be added for many board support packages
#cd <full path name to boot directory>
ld < iocCore
ld < seq
ld < APPNAMESupport
dbLoadDatabase("../../dbd/APPNAME.dbd")
END
if [ -n "${EXAMPLES}" ]; then
sed -e "s/USER/${USER}/" \
-e "s/APPNAME/${APPNAME}/" >> src/st.${APPNAME} <<-\END
dbLoadRecords("../../APPNAME/db/dbExample.db","user=USER")
iocInit
seq &snctest
END
else
sed -e "s/USER/${USER}/" \
-e "s/APPNAME/${APPNAME}/" >> src/st.${APPNAME} <<-\END
#dbLoadRecords("../../APPNAME/db/xxx.db","user=USER")
iocInit
#start sequence programs
#seq &sncxxx
END
fi
if [ -z "${EXAMPLES}" ]; then Cleanup 0; fi;
#if source starts with blank tab replace by tab
sed -e "s/ / /" > src/caExample.c <<-\END
/*caExample.c*/
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cadef.h>
main(int argc,char **argv)
{
double data;
int status;
chid mychid;
if(argc != 2) {
fprintf(stderr,"usage: caExample pvname\n");
exit(1);
}
SEVCHK(ca_task_initialize(),"ca_task_initialize");
SEVCHK(ca_search(argv[1],&mychid),"ca_search failure");
SEVCHK(ca_pend_io(5.0),"ca_pend_io failure");
SEVCHK(ca_get(DBR_DOUBLE,mychid,(void *)&data),"ca_get failure");
SEVCHK(ca_pend_io(5.0),"ca_pend_io failure");
printf("%s %f\n",argv[1],data);
return(0);
}
END
#if source starts with blank tab replace by tab
sed -e "s/ / /" > src/xxxRecord.c <<-\END
/* recXxx.c */
/* Example record support module */
#include <vxWorks.h>
#include <stddef.h>
#include <stdio.h>
#include <lstLib.h>
#include <string.h>
#include <alarm.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <devSup.h>
#include <errMdef.h>
#include <recSup.h>
#include <special.h>
#define GEN_SIZE_OFFSET
#include <xxxRecord.h>
#undef GEN_SIZE_OFFSET
/* Create RSET - Record Support Entry Table*/
#define report NULL
#define initialize NULL
static long init_record();
static long process();
#define special NULL
#define get_value NULL
#define cvt_dbaddr NULL
#define get_array_info NULL
#define put_array_info NULL
static long get_units();
static long get_precision();
#define get_enum_str NULL
#define get_enum_strs NULL
#define put_enum_str NULL
static long get_graphic_double();
static long get_control_double();
static long get_alarm_double();
struct rset xxxRSET={
RSETNUMBER,
report,
initialize,
init_record,
process,
special,
get_value,
cvt_dbaddr,
get_array_info,
put_array_info,
get_units,
get_precision,
get_enum_str,
get_enum_strs,
put_enum_str,
get_graphic_double,
get_control_double,
get_alarm_double};
typedef struct xxxset { /* xxx input dset */
long number;
DEVSUPFUN dev_report;
DEVSUPFUN init;
DEVSUPFUN init_record; /*returns: (-1,0)=>(failure,success)*/
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_xxx;
}xxxdset;
static void alarm(xxxRecord *pxxx);
static void convert(xxxRecord *pxxx);
static void monitor(xxxRecord *pxxx);
static long init_record(void *precord,int pass)
{
xxxRecord *pxxx = (xxxRecord *)precord;
xxxdset *pdset;
long status;
if (pass==0) return(0);
if(!(pdset = (xxxdset *)(pxxx->dset))) {
recGblRecordError(S_dev_noDSET,(void *)pxxx,"xxx: init_record");
return(S_dev_noDSET);
}
/* must have read_xxx function defined */
if( (pdset->number < 5) || (pdset->read_xxx == NULL) ) {
recGblRecordError(S_dev_missingSup,(void *)pxxx,"xxx: init_record");
return(S_dev_missingSup);
}
if( pdset->init_record ) {
if((status=(*pdset->init_record)(pxxx))) return(status);
}
return(0);
}
static long process(void *precord)
{
xxxRecord *pxxx = (xxxRecord *)precord;
xxxdset *pdset = (xxxdset *)(pxxx->dset);
long status;
unsigned char pact=pxxx->pact;
if( (pdset==NULL) || (pdset->read_xxx==NULL) ) {
pxxx->pact=TRUE;
recGblRecordError(S_dev_missingSup,(void *)pxxx,"read_xxx");
return(S_dev_missingSup);
}
/* pact must not be set until after calling device support */
status=(*pdset->read_xxx)(pxxx);
/* check if device support set pact */
if ( !pact && pxxx->pact ) return(0);
pxxx->pact = TRUE;
recGblGetTimeStamp(pxxx);
/* check for alarms */
alarm(pxxx);
/* check event list */
monitor(pxxx);
/* process the forward scan link record */
recGblFwdLink(pxxx);
pxxx->pact=FALSE;
return(status);
}
static long get_units(DBADDR *paddr, char *units)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
strncpy(units,pxxx->egu,DB_UNITS_SIZE);
return(0);
}
static long get_precision(DBADDR *paddr, long *precision)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
*precision = pxxx->prec;
if(paddr->pfield == (void *)&pxxx->val) return(0);
recGblGetPrec(paddr,precision);
return(0);
}
static long get_graphic_double(DBADDR *paddr,struct dbr_grDouble *pgd)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
int fieldIndex = dbGetFieldIndex(paddr);
if(fieldIndex == xxxRecordVAL
|| fieldIndex == xxxRecordHIHI
|| fieldIndex == xxxRecordHIGH
|| fieldIndex == xxxRecordLOW
|| fieldIndex == xxxRecordLOLO
|| fieldIndex == xxxRecordHOPR
|| fieldIndex == xxxRecordLOPR) {
pgd->upper_disp_limit = pxxx->hopr;
pgd->lower_disp_limit = pxxx->lopr;
} else recGblGetGraphicDouble(paddr,pgd);
return(0);
}
static long get_control_double(DBADDR *paddr,struct dbr_ctrlDouble *pcd)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
int fieldIndex = dbGetFieldIndex(paddr);
if(fieldIndex == xxxRecordVAL
|| fieldIndex == xxxRecordHIHI
|| fieldIndex == xxxRecordHIGH
|| fieldIndex == xxxRecordLOW
|| fieldIndex == xxxRecordLOLO) {
pcd->upper_ctrl_limit = pxxx->hopr;
pcd->lower_ctrl_limit = pxxx->lopr;
} else recGblGetControlDouble(paddr,pcd);
return(0);
}
static long get_alarm_double(DBADDR *paddr,struct dbr_alDouble *pad)
{
xxxRecord *pxxx=(xxxRecord *)paddr->precord;
int fieldIndex = dbGetFieldIndex(paddr);
if(fieldIndex == xxxRecordVAL) {
pad->upper_alarm_limit = pxxx->hihi;
pad->upper_warning_limit = pxxx->high;
pad->lower_warning_limit = pxxx->low;
pad->lower_alarm_limit = pxxx->lolo;
} else recGblGetAlarmDouble(paddr,pad);
return(0);
}
static void alarm(xxxRecord *pxxx)
{
double val;
float hyst, lalm, hihi, high, low, lolo;
unsigned short hhsv, llsv, hsv, lsv;
if(pxxx->udf == TRUE ){
recGblSetSevr(pxxx,UDF_ALARM,INVALID_ALARM);
return;
}
hihi = pxxx->hihi; lolo = pxxx->lolo; high = pxxx->high; low = pxxx->low;
hhsv = pxxx->hhsv; llsv = pxxx->llsv; hsv = pxxx->hsv; lsv = pxxx->lsv;
val = pxxx->val; hyst = pxxx->hyst; lalm = pxxx->lalm;
/* alarm condition hihi */
if (hhsv && (val >= hihi || ((lalm==hihi) && (val >= hihi-hyst)))){
if (recGblSetSevr(pxxx,HIHI_ALARM,pxxx->hhsv)) pxxx->lalm = hihi;
return;
}
/* alarm condition lolo */
if (llsv && (val <= lolo || ((lalm==lolo) && (val <= lolo+hyst)))){
if (recGblSetSevr(pxxx,LOLO_ALARM,pxxx->llsv)) pxxx->lalm = lolo;
return;
}
/* alarm condition high */
if (hsv && (val >= high || ((lalm==high) && (val >= high-hyst)))){
if (recGblSetSevr(pxxx,HIGH_ALARM,pxxx->hsv)) pxxx->lalm = high;
return;
}
/* alarm condition low */
if (lsv && (val <= low || ((lalm==low) && (val <= low+hyst)))){
if (recGblSetSevr(pxxx,LOW_ALARM,pxxx->lsv)) pxxx->lalm = low;
return;
}
/* we get here only if val is out of alarm by at least hyst */
pxxx->lalm = val;
return;
}
static void monitor(xxxRecord *pxxx)
{
unsigned short monitor_mask;
double delta;
monitor_mask = recGblResetAlarms(pxxx);
/* check for value change */
delta = pxxx->mlst - pxxx->val;
if(delta<0.0) delta = -delta;
if (delta > pxxx->mdel) {
/* post events for value change */
monitor_mask |= DBE_VALUE;
/* update last value monitored */
pxxx->mlst = pxxx->val;
}
/* check for archive change */
delta = pxxx->alst - pxxx->val;
if(delta<0.0) delta = -delta;
if (delta > pxxx->adel) {
/* post events on value field for archive change */
monitor_mask |= DBE_LOG;
/* update last archive value monitored */
pxxx->alst = pxxx->val;
}
/* send out monitors connected to the value field */
if (monitor_mask){
db_post_events(pxxx,&pxxx->val,monitor_mask);
}
return;
}
END
#if source starts with blank tab replace by tab
sed -e "s/ / /" > src/xxxRecord.dbd <<-\END
recordtype(xxx) {
include "dbCommon.dbd"
field(VAL,DBF_DOUBLE) {
prompt("Current EGU Value")
asl(ASL0)
pp(TRUE)
}
field(INP,DBF_INLINK) {
prompt("Input Specification")
promptgroup(GUI_INPUTS)
special(SPC_NOMOD)
interest(1)
}
field(PREC,DBF_SHORT) {
prompt("Display Precision")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(EGU,DBF_STRING) {
prompt("Engineering Units")
promptgroup(GUI_DISPLAY)
interest(1)
size(16)
}
field(HOPR,DBF_FLOAT) {
prompt("High Operating Range")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(LOPR,DBF_FLOAT) {
prompt("Low Operating Range")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(HIHI,DBF_FLOAT) {
prompt("Hihi Alarm Limit")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
}
field(LOLO,DBF_FLOAT) {
prompt("Lolo Alarm Limit")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
}
field(HIGH,DBF_FLOAT) {
prompt("High Alarm Limit")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
}
field(LOW,DBF_FLOAT) {
prompt("Low Alarm Limit")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
}
field(HHSV,DBF_MENU) {
prompt("Hihi Severity")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(LLSV,DBF_MENU) {
prompt("Lolo Severity")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(HSV,DBF_MENU) {
prompt("High Severity")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(LSV,DBF_MENU) {
prompt("Low Severity")
promptgroup(GUI_ALARMS)
pp(TRUE)
interest(1)
menu(menuAlarmSevr)
}
field(HYST,DBF_DOUBLE) {
prompt("Alarm Deadband")
promptgroup(GUI_ALARMS)
interest(1)
}
field(ADEL,DBF_DOUBLE) {
prompt("Archive Deadband")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(MDEL,DBF_DOUBLE) {
prompt("Monitor Deadband")
promptgroup(GUI_DISPLAY)
interest(1)
}
field(LALM,DBF_DOUBLE) {
prompt("Last Value Alarmed")
special(SPC_NOMOD)
interest(3)
}
field(ALST,DBF_DOUBLE) {
prompt("Last Value Archived")
special(SPC_NOMOD)
interest(3)
}
field(MLST,DBF_DOUBLE) {
prompt("Last Val Monitored")
special(SPC_NOMOD)
interest(3)
}
}
END
#if source starts with blank tab replace by tab
sed -e "s/ / /" > src/devXxxSoft.c <<-\END
/* devXxxSoft.c */
/* Example device support module */
#include <vxWorks.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <alarm.h>
#include <cvtTable.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <recSup.h>
#include <devSup.h>
#include <link.h>
#include <xxxRecord.h>
/* Added for Channel Access Links */
long dbCaAddInlink();
long dbCaGetLink();
/*Create the dset for devXxxSoft */
static long init_record();
static long read_xxx();
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_xxx;
}devXxxSoft={
5,
NULL,
NULL,
init_record,
NULL,
read_xxx,
};
static long init_record(pxxx)
struct xxxRecord *pxxx;
{
long status;
/* xxx.inp must be a CONSTANT or a PV_LINK or a DB_LINK or a CA_LINK*/
switch (pxxx->inp.type) {
case (CONSTANT) :
if(recGblInitConstantLink(&pxxx->inp,DBF_DOUBLE,&pxxx->val))
pxxx->udf = FALSE;
break;
case (PV_LINK) :
case (CA_LINK) :
case (DB_LINK) :
break;
default :
recGblRecordError(S_db_badField, (void *)pxxx,
"devXxxSoft (init_record) Illegal INP field");
return(S_db_badField);
}
return(0);
}
static long read_xxx(pxxx)
struct xxxRecord *pxxx;
{
long status;
status = dbGetLink(&(pxxx->inp),DBF_DOUBLE, &(pxxx->val),0,0);
if (RTN_SUCCESS(status))
pxxx->udf = FALSE;
return(0);
}
END
#if source starts with blank tab replace by tab
sed -e "s/USER/${USER}/" \
-e "s/ / /" > src/sncExample.st <<-\END
program snctest
float v;
assign v to "USER:xxxExample";
monitor v;
ss ss1
{
state low
{
when(v>5.0)
{
printf("changing to high\n");
} state high
when(delay(.1))
{
} state low
}
state high
{
when(v<=5.0)
{
printf("changing to low\n");
} state low
when(delay(.1))
{
} state high
}
}
END
cd ..
echo "add line to Makefile DIRS+=$APPNAME "
done
Cleanup 0