252 lines
5.7 KiB
C
252 lines
5.7 KiB
C
|
/*
|
||
|
* iFlow - IntelliFlow simulator on <bus>
|
||
|
*/
|
||
|
#define APRS485_API 1
|
||
|
#include "aprs485.h"
|
||
|
#include "pa_iflo.h"
|
||
|
|
||
|
char version[] = "@(#) iFlow 0.04";
|
||
|
|
||
|
struct {
|
||
|
u08_t adr;
|
||
|
u08_t dsp;
|
||
|
int eprg;
|
||
|
int chg;
|
||
|
u08_t sp_man_gpm;
|
||
|
u08_t sp_gpm;
|
||
|
u08_t sp_epgpm[5];
|
||
|
int sp_eprpm[5];
|
||
|
iflsr_t isr;
|
||
|
} gl;
|
||
|
|
||
|
pa5_t *pa5_rcv(u08_t *buf, int nbu)
|
||
|
{
|
||
|
pa5_t *pr;
|
||
|
u08_t *b, *c, *e;
|
||
|
u16_t sum;
|
||
|
int n;
|
||
|
|
||
|
if ((n = nbu) < sizeof(pa5_t)) return 0;
|
||
|
for (e = (b = buf) + n; b < e && *b != 0xa5; b++);
|
||
|
if ((e - b) < sizeof(pa5_t)) return 0;
|
||
|
pr = (pa5_t *)b;
|
||
|
if (((c = &pr->dat[pr->len]) + 2) < e || pr->dst != gl.adr) return 0;
|
||
|
for (sum = 0; b < c; sum += *b++);
|
||
|
if (sum != ((c[0]<<8)+c[1])) return 0;
|
||
|
return pr;
|
||
|
}
|
||
|
|
||
|
void pa5_snd(int bd, pa5_t *ps)
|
||
|
{
|
||
|
int n, k;
|
||
|
u16_t sum;
|
||
|
u08_t *b, *s, snd[PA5SIZ];
|
||
|
|
||
|
for (b = snd, n = 3; --n >= 0; *b++ = 0xff); b[-2] = 0;
|
||
|
n = sizeof(*ps) + ps->len;
|
||
|
for (sum = 0, s = &ps->lpb; --n >= 0; b++) sum += *b = *s++;
|
||
|
*b++ = sum>>8;
|
||
|
*b++ = sum>>0;
|
||
|
n = b - snd;
|
||
|
k = write(bd,snd,n);
|
||
|
if (k != n) printf("write(%d)=%d!!!\n",n,k);
|
||
|
}
|
||
|
|
||
|
void cmd_in(int bd, pa5_t *pr)
|
||
|
{
|
||
|
pa5_t *ps;
|
||
|
u16_t adr, val;
|
||
|
iflsr_t isn;
|
||
|
u08_t buf[64];
|
||
|
|
||
|
*(ps = (pa5_t *)buf) = *pr;
|
||
|
ps->dst = pr->src;
|
||
|
ps->src = gl.adr;
|
||
|
switch (pr->cfi) {
|
||
|
default: return; break;
|
||
|
case IFLO_REG:
|
||
|
if (pr->len != 4) return;
|
||
|
adr = (pr->dat[0]<<8)+pr->dat[1];
|
||
|
val = (pr->dat[2]<<8)+pr->dat[3];
|
||
|
switch (adr) {
|
||
|
default: return; break;
|
||
|
case IFLO_REG_SPGPM: gl.sp_gpm = val; break;
|
||
|
case IFLO_REG_EPRG:
|
||
|
switch (val) {
|
||
|
default: return; break;
|
||
|
case IFLO_EPRG_P0:
|
||
|
case IFLO_EPRG_P1:
|
||
|
case IFLO_EPRG_P2:
|
||
|
case IFLO_EPRG_P3:
|
||
|
case IFLO_EPRG_P4:
|
||
|
gl.eprg = val;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case IFLO_REG_EP1RPM: gl.sp_eprpm[1] = val; break;
|
||
|
case IFLO_REG_EP2RPM: gl.sp_eprpm[2] = val; break;
|
||
|
case IFLO_REG_EP3RPM: gl.sp_eprpm[3] = val; break;
|
||
|
case IFLO_REG_EP4RPM: gl.sp_eprpm[4] = val; break;
|
||
|
}
|
||
|
ps->len = 2;
|
||
|
ps->dat[0] = val>>8;
|
||
|
ps->dat[1] = val>>0;
|
||
|
break;
|
||
|
case IFLO_DSP:
|
||
|
if (pr->len != 1) return;
|
||
|
switch (pr->dat[0]) {
|
||
|
default: return; break;
|
||
|
case IFLO_DSP_LOC:
|
||
|
case IFLO_DSP_REM:
|
||
|
if (gl.dsp != pr->dat[0]) gl.chg = 5;
|
||
|
gl.dsp = ps->dat[0] = pr->dat[0];
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case IFLO_MOD:
|
||
|
if (pr->len != 1) return;
|
||
|
if (gl.isr.mod != pr->dat[0]) gl.chg = 6;
|
||
|
gl.isr.mod = ps->dat[0] = pr->dat[0];
|
||
|
break;
|
||
|
case IFLO_RUN:
|
||
|
if (pr->len != 1) return;
|
||
|
switch (pr->dat[0]) {
|
||
|
default: return;
|
||
|
case IFLO_RUN_STRT:
|
||
|
case IFLO_RUN_STOP:
|
||
|
if (gl.isr.run != pr->dat[0]) gl.chg = 7;
|
||
|
gl.isr.run = ps->dat[0] = pr->dat[0];
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case IFLO_SRG:
|
||
|
if (gl.dsp != IFLO_DSP_REM) return;
|
||
|
if (pr->len != 0) return;
|
||
|
gl.isr.gpm = 0;
|
||
|
if (gl.isr.run == IFLO_RUN_STRT) {
|
||
|
switch (gl.isr.mod) {
|
||
|
case IFLO_MOD_MANUAL:
|
||
|
if (gl.isr.gpm != gl.sp_man_gpm) gl.chg = 8;
|
||
|
gl.isr.gpm = gl.sp_man_gpm;
|
||
|
break;
|
||
|
case IFLO_MOD_FILTER:
|
||
|
case IFLO_MOD_EXT_P1:
|
||
|
case IFLO_MOD_EXT_P2:
|
||
|
case IFLO_MOD_EXT_P3:
|
||
|
case IFLO_MOD_EXT_P4:
|
||
|
switch (gl.eprg) {
|
||
|
case IFLO_EPRG_P0: gl.isr.gpm = gl.sp_epgpm[0]; gl.isr.mod = IFLO_MOD_FILTER; break;
|
||
|
case IFLO_EPRG_P1: gl.isr.gpm = gl.sp_epgpm[1]; gl.isr.mod = IFLO_MOD_EXT_P1; break;
|
||
|
case IFLO_EPRG_P2: gl.isr.gpm = gl.sp_epgpm[2]; gl.isr.mod = IFLO_MOD_EXT_P2; break;
|
||
|
case IFLO_EPRG_P3: gl.isr.gpm = gl.sp_epgpm[3]; gl.isr.mod = IFLO_MOD_EXT_P3; break;
|
||
|
case IFLO_EPRG_P4: gl.isr.gpm = gl.sp_epgpm[4]; gl.isr.mod = IFLO_MOD_EXT_P4; break;
|
||
|
}
|
||
|
break;
|
||
|
case 6:
|
||
|
if (gl.isr.gpm != gl.sp_gpm) gl.chg = 9;
|
||
|
gl.isr.gpm = gl.sp_gpm;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
switch (gl.isr.mod) {
|
||
|
case IFLO_MOD_EXT_P1:
|
||
|
case IFLO_MOD_EXT_P2:
|
||
|
case IFLO_MOD_EXT_P3:
|
||
|
case IFLO_MOD_EXT_P4:
|
||
|
gl.chg++;
|
||
|
gl.isr.mod = IFLO_MOD_FILTER;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
if (gl.isr.gpm == 0) gl.isr.rpm = 0;
|
||
|
else gl.isr.rpm = gl.isr.gpm * 50;
|
||
|
gl.isr.pwr = (2000 * gl.isr.rpm) / 3450;
|
||
|
isn = gl.isr;
|
||
|
isn.pwr = htons(isn.pwr);
|
||
|
isn.rpm = htons(isn.rpm);
|
||
|
bcopy(&isn,ps->dat,ps->len=sizeof(isn));
|
||
|
break;
|
||
|
}
|
||
|
pa5_snd(bd,ps);
|
||
|
}
|
||
|
|
||
|
void iflow(int bd)
|
||
|
{
|
||
|
pa5_t *pr;
|
||
|
fd_set pfds, rfds;
|
||
|
tmv_t tc, tv;
|
||
|
int pks, n;
|
||
|
u08_t pkb[PA5SIZ];
|
||
|
struct tm tm;
|
||
|
|
||
|
FD_ZERO(&pfds);
|
||
|
FD_SET(0,&pfds);
|
||
|
FD_SET(bd,&pfds);
|
||
|
gettimeofday(&tc,0);
|
||
|
localtime_r(&tc.tv_sec,&tm);
|
||
|
while (1) {
|
||
|
tv.tv_sec = 30; tv.tv_usec = 0;
|
||
|
rfds = pfds;
|
||
|
if (gl.chg) printf("\n");
|
||
|
printf("\r%02d:%02d:%02d dsp=%02x run=%02x mod=%02x rpm=%-4d pwr=%-4d gpm=%-3d err=%02x ",
|
||
|
tm.tm_hour,tm.tm_min,tm.tm_sec,
|
||
|
gl.dsp,gl.isr.run,gl.isr.mod,gl.isr.rpm,gl.isr.pwr,gl.isr.gpm,gl.isr.err);
|
||
|
fflush(stdout);
|
||
|
gl.chg = 0;
|
||
|
if ((n = select(bd+1,&rfds,0,0,&tv)) < 0 && errno != EINTR) break;
|
||
|
if (n <= 0) continue;
|
||
|
gettimeofday(&tc,0);
|
||
|
localtime_r(&tc.tv_sec,&tm);
|
||
|
gl.isr.clk[0] = tm.tm_hour;
|
||
|
gl.isr.clk[1] = tm.tm_min;
|
||
|
if (FD_ISSET(bd,&rfds)) {
|
||
|
pks = read(bd,pkb,sizeof(pkb));
|
||
|
if (pks == 2 && pkb[0] == EOT) {
|
||
|
printf("EOT from hub\n");
|
||
|
break;
|
||
|
}
|
||
|
if ((pr = pa5_rcv(pkb,pks))) cmd_in(bd,pr);
|
||
|
}
|
||
|
if (FD_ISSET(0,&rfds)) {
|
||
|
n = read(0,pkb,sizeof(pkb));
|
||
|
if (n < 1 || pkb[0] == 'q') break;
|
||
|
if (pkb[0] == 'E') gl.isr.err ^= 0x80;
|
||
|
if (pkb[0] == 'S' && gl.dsp == IFLO_DSP_LOC) {
|
||
|
if (gl.isr.run != IFLO_RUN_STOP)
|
||
|
gl.isr.run = IFLO_RUN_STOP;
|
||
|
else gl.isr.run = IFLO_RUN_STRT;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int main(int ac, char **av)
|
||
|
{
|
||
|
int bd;
|
||
|
char msg[128];
|
||
|
|
||
|
bzero(&gl,sizeof(gl));
|
||
|
gl.adr = 0x60;
|
||
|
gl.dsp = IFLO_DSP_LOC;
|
||
|
gl.sp_man_gpm = 30;
|
||
|
gl.sp_epgpm[1] = 20;
|
||
|
gl.sp_epgpm[2] = 25;
|
||
|
gl.sp_epgpm[3] = 30;
|
||
|
gl.sp_epgpm[4] = 36;
|
||
|
gl.sp_eprpm[1] = 1000;
|
||
|
gl.sp_eprpm[2] = 2000;
|
||
|
gl.sp_eprpm[3] = 2500;
|
||
|
gl.sp_eprpm[4] = 3450;
|
||
|
gl.isr.run = IFLO_RUN_STOP;
|
||
|
gl.isr.pmp = IFLO_PMP_READY;
|
||
|
gl.isr.mod = IFLO_MOD_MANUAL;
|
||
|
bd = hub_at(ac>1?av[1]:0,msg);
|
||
|
printf("%s: %s\n",av[0],msg);
|
||
|
if (bd < 0) return -1;
|
||
|
iflow(bd);
|
||
|
hub_dt(bd);
|
||
|
return 0;
|
||
|
}
|
||
|
|