A => sky/cmd/cfg.c +323 -0
@@ 0,0 1,323 @@
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <bio.h>
+#include <draw.h>
+
+#include "debug.h"
+#include "lex.h"
+#include "sky.h"
+#include "gfx.h"
+
+#include "dat.h"
+#include "fns.h"
+
+enum
+{
+ DTstr,
+ DTdouble,
+ DTint,
+};
+
+Cfg *cfg;
+
+double runeatof(Rune *s);
+Rune *runestrtok(Rune *s1, Rune *s2);
+struct Skynode *mkskynode(void);
+void *findaddr(Rune *id, int *typ, int *dtyp);
+
+int
+cfginit(void)
+{
+ if((cfg = malloc(sizeof(Cfg))) == nil)
+ return Ememory;
+ if((cfg->head=mkskynode())==nil)
+ return Ememory;
+ memset(cfg->head, 0, sizeof(struct Skynode));
+
+ cfg->obs = defaultObs;
+ cfg->camera = defaultCamera;
+ cfg->jd = time(0)/86400.0 + 2440587.5; /* now */
+ cfg->atm = 1;
+
+ return 0;
+}
+
+void
+cfgterm(void)
+{
+ struct Skynode *head, *nxt;
+ head = cfg->head;
+
+ while(head){
+ nxt = head->next;
+ free(head);
+ head = nxt;
+ }
+ free(cfg);
+}
+
+int cfginsert(Tok *argv, int argc)
+{
+ struct Skynode *head;
+ int typ, dtyp;
+
+ head = cfg->head;
+
+ if(argc != 1 || argv->typ != Tidentifier) return Einvalid;
+
+ if(findaddr(argv->str, &typ, &dtyp)) return Einvalid;
+ /* the tail node is always pre-allocated but unset */
+ while(head->next)
+ head=head->next;
+
+ if((head->next=mkskynode())==nil)
+ return Ememory;
+
+ runestrncpy(head->id, argv->str, Ltoksize+1);
+
+ return 0;
+}
+
+int cfgset(Tok *argv, int argc)
+{
+ struct Skynode *head;
+ void *addr;
+ int typ, dtyp;
+
+ head = cfg->head;
+
+ if(argc != 2 || (addr = findaddr(argv->str, &typ, &dtyp)) == nil) return Einvalid;
+ argv++;
+ if(argv->typ != typ) return Einvalid;
+
+ switch(dtyp){
+ case DTstr:
+ runestrncpy(addr, argv->str, Ltoksize+1);
+ break;
+ case DTdouble:
+ *(double*)addr = runeatof(argv->str);
+ break;
+ case DTint:
+ *(int*)addr = runeatof(argv->str);
+ break;
+ default:
+ return Einvalid; /* should not happen */
+ }
+
+ return 0;
+}
+
+int cfgdraw(Tok *argv, int argc)
+{
+ struct Skynode *head;
+ Hzloc hz;
+ Planar p;
+ Point pt;
+ RGBi c;
+
+ head = cfg->head;
+
+ if(argc != 0) return Einvalid;
+
+ /* the tail node is always pre-allocated but unset */
+ while(head->next){
+ hz = eq2hz(gx2eq00(head->gx), cfg->obs.g, cfg->jd, 0, 0);
+ if(cfg->atm) hz.z += saemundsson(&cfg->obs, hz.z);
+ p = hz2pxl(&cfg->camera, hz);
+ pt.x = p.x + cfg->camera.wpx/2; pt.y = p.y + cfg->camera.hpx/2;
+ c.r = head->r; c.g = head->g; c.b = head->b;
+ marker(screen, pt, c, head->size, Mdisc, head->str);
+ head=head->next;
+ }
+
+ return 0;
+}
+
+double
+runeatof(Rune *s)
+{
+ char cs[Ltoksize+1], *c;
+ int i;
+
+ for(i=0, c=cs; i<Ltoksize && *s; i++)
+ *c++ = *s++;
+ *c = '\0';
+
+ return atof(cs);
+}
+
+Rune*
+runestrtok(Rune *s, Rune *b)
+{
+ static Rune *saved;
+ Rune *sc, *bc;
+
+ if(s == 0) s = saved;
+
+ sc = s;
+ while(*sc){
+ for(bc=b; *bc; bc++) if(*sc == *bc){
+ *sc++ = L'\0';
+ saved = sc;
+ return s;
+ }
+ sc++;
+ }
+ saved = L"";
+ return s;
+}
+
+struct Skynode*
+mkskynode(void)
+{
+ struct Skynode *h;
+ if((h=malloc(sizeof(struct Skynode)))==nil)
+ return nil;
+ memset(h, 0, sizeof(struct Skynode));
+
+ return h;
+}
+
+void*
+findaddr(Rune *id, int *typ, int *dtyp)
+{
+ struct Skynode *head;
+ Rune *t, tmp[Ltoksize+1];
+
+ head = cfg->head;
+ runestrncpy(tmp, id, Ltoksize+1);
+ tmp[Ltoksize] = L'\0';
+
+ DBPRINT(20, "cfg.c:findaddr %S ", id);
+
+ t = runestrtok(tmp, L".");
+
+ DBPRINT(20, "t=%S ", t);
+ if(!runestrcmp(t, L"obs")){
+ if((t = runestrtok(0, L".")) == 0) return nil;
+ DBPRINT(20, "obs. t=%S ", t);
+ if(!runestrcmp(t, L"g")){
+ if((t = runestrtok(0, L".")) == 0) return nil;
+ DBPRINT(20, "g. t=%S ", t);
+ *typ = Tdecimal;
+ *dtyp = DTdouble;
+ if(!runestrcmp(t, L"lat"))
+ return &cfg->obs.g.lat;
+ if(!runestrcmp(t, L"lng"))
+ return &cfg->obs.g.lng;
+ if(!runestrcmp(t, L"alt"))
+ return &cfg->obs.g.alt;
+
+ return nil;
+ }
+ return nil;
+ }
+
+ if(!runestrcmp(t, L"camera")){
+ if((t = runestrtok(0, L".")) == 0) return nil;
+ DBPRINT(20, "camera. t=%S ", t);
+ if(!runestrcmp(t, L"f")){
+ *typ = Tdecimal;
+ *dtyp = DTdouble;
+ return &cfg->camera.f;
+ }
+ if(!runestrcmp(t, L"w")){
+ *typ = Tdecimal;
+ *dtyp = DTdouble;
+ return &cfg->camera.w;
+ }
+ if(!runestrcmp(t, L"h")){
+ *typ = Tdecimal;
+ *dtyp = DTdouble;
+ return &cfg->camera.h;
+ }
+ if(!runestrcmp(t, L"wpx")){
+ *typ = Tdecimal;
+ *dtyp = DTdouble;
+ return &cfg->camera.wpx;
+ }
+ if(!runestrcmp(t, L"hpx")){
+ *typ = Tdecimal;
+ *dtyp = DTdouble;
+ return &cfg->camera.hpx;
+ }
+ if(!runestrcmp(t, L"angle")){
+ if((t = runestrtok(0, L".")) == 0) return nil;
+ DBPRINT(20, "angle. t=%S ", t);
+ *typ = Tdecimal;
+ *dtyp = DTdouble;
+ if(!runestrcmp(t, L"az"))
+ return &cfg->camera.angle.az;
+ if(!runestrcmp(t, L"z"))
+ return &cfg->camera.angle.z;
+ if(!runestrcmp(t, L"roll"))
+ return &cfg->camera.angle.roll;
+
+ return nil;
+ }
+ return nil;
+ }
+
+ if(!runestrcmp(t, L"jd")){
+ *typ = Tdecimal;
+ *dtyp = DTdouble;
+ return &cfg->jd;
+ }
+
+ if(!runestrcmp(t, L"atm")){
+ *typ = Tdecimal;
+ *dtyp = DTint;
+ return &cfg->atm;
+ }
+
+ /* is it an object identifier? (last one is always unset) */
+ while(head->next){
+ if(!runestrcmp(t, head->id)){
+ if((t = runestrtok(0, L".")) == 0) return nil;
+ DBPRINT(20, "node:%S. t=%S ", head->id, t);
+ if(!runestrcmp(t, L"str")){
+ *typ = Tstr;
+ *dtyp = DTstr;
+ return head->str;
+ }
+ if(!runestrcmp(t, L"gx")){
+ if((t = runestrtok(0, L".")) == 0) return nil;
+ DBPRINT(20, "gx. t=%S ", t);
+ *typ = Tdecimal;
+ *dtyp = DTdouble;
+ if(!runestrcmp(t, L"b"))
+ return &head->gx.b;
+ if(!runestrcmp(t, L"l"))
+ return &head->gx.l;
+
+ return nil;
+ }
+ if(!runestrcmp(t, L"r")){
+ *typ = Tdecimal;
+ *dtyp = DTint;
+ return &head->r;
+ }
+ if(!runestrcmp(t, L"g")){
+ *typ = Tdecimal;
+ *dtyp = DTint;
+ return &head->g;
+ }
+ if(!runestrcmp(t, L"b")){
+ *typ = Tdecimal;
+ *dtyp = DTint;
+ return &head->b;
+ }
+ if(!runestrcmp(t, L"size")){
+ *typ = Tdecimal;
+ *dtyp = DTint;
+ return &head->size;
+ }
+
+ return nil;
+ }
+ head = head->next;
+ }
+
+ return nil;
+}
M sky/cmd/cmd.c +18 -12
@@ 5,11 5,14 @@
#include "debug.h"
#include "lex.h"
+#include "sky.h"
#include "dat.h"
#include "fns.h"
-struct Cmdnode *mknode(void);
+Lexer l;
+
+struct Cmdnode *mkcmdnode(void);
int eqsig(Cmd *c1, Cmd *c2);
int (*(getfun)(struct Cmdnode*, Cmd*))(Tok*, int);
@@ 19,8 22,8 @@ mkcmdctxt(int fd)
Cmdctxt *ctxt;
if((ctxt=malloc(sizeof(Cmdctxt)))==nil)
return nil;
- ctxt->fd = fd;
- if((ctxt->head=mknode())==nil){
+ linit(&ctxt->l, fd, lexstart());
+ if((ctxt->head=mkcmdnode())==nil){
free(ctxt);
return nil;
}
@@ 44,8 47,8 @@ cmdreg(Cmdctxt *ctxt, Cmd *c)
head=head->next;
}
- if((head->next=mknode())==nil)
- return Loverflow;
+ if((head->next=mkcmdnode())==nil)
+ return Ememory;
*(head->c) = *c;
@@ 64,26 67,24 @@ cmdterm(Cmdctxt *ctxt)
free(head);
head = nxt;
}
+
+ lterm(&ctxt->l);
+ free(ctxt);
}
void
cmdproc(void *ctxt)
{
struct Cmdnode *head;
- int fd;
- Lexer l;
Tok t, argv[Cmaxargs];
Cmd c;
int (*efun)(Tok*, int);
char *err;
head = ((Cmdctxt*)ctxt)->head;
- fd = ((Cmdctxt*)ctxt)->fd;
memset(&c, 0, sizeof(Cmd));
- linit(&l, fd, lexstart());
-
- while(t = lnexttok(&l), t.typ != Teof){
+ while(t = lnexttok(&((Cmdctxt*)ctxt)->l), t.typ != Teof){
DBPRINT(10, "tok: %d(%S)\n", t.typ, t.str);
switch(t.typ){
case Terror:
@@ 103,6 104,11 @@ error: fprint(2, "%s in cmd %S (last to
err = "invalid data";
goto error;
}
+ DBIF(10) {
+ fprint(2, "cmd %S with args in reverse:", c.str);
+ while(c.argc) fprint(2, " %S", argv[--c.argc].str);
+ fprint(2, ": success\n");
+ }
memset(&c, 0, sizeof(Cmd));
break;
case Tidentifier:
@@ 117,7 123,7 @@ error: fprint(2, "%s in cmd %S (last to
}
struct Cmdnode*
-mknode(void)
+mkcmdnode(void)
{
struct Cmdnode *h;
if((h=malloc(sizeof(struct Cmdnode)))==nil)
M sky/cmd/dat.h +31 -2
@@ 1,5 1,6 @@
typedef struct Cmd Cmd;
typedef struct Cmdctxt Cmdctxt;
+typedef struct Cfg Cfg;
enum
{
@@ 16,7 17,13 @@ enum
enum
{
Cmaxargs = 32,
- Coverflow = -10,
+};
+
+enum
+{
+ Einvalid = -20,
+ Ememory = -10,
+ Efailed = -1,
};
struct Cmd
@@ 35,6 42,28 @@ struct Cmdnode
struct Cmdctxt
{
struct Cmdnode *head;
- int fd;
+ Lexer l;
};
+struct Skynode
+{
+ Rune id[Ltoksize+1];
+ Rune str[Ltoksize+1];
+ Gxloc gx;
+ int r,g,b;
+ int size;
+
+ struct Skynode *next;
+};
+
+struct Cfg
+{
+ Obs obs;
+ Camera camera;
+ double jd;
+ int atm;
+
+ struct Skynode *head;
+};
+
+extern Cfg *cfg;
M sky/cmd/fns.h +8 -1
@@ 5,4 5,11 @@ State lexstart(void);
Cmdctxt *mkcmdctxt(int fd);
int cmdreg(Cmdctxt *ctxt, Cmd *c);
void cmdproc(void *ctxt);
-void cmdterm(Cmdctxt *ctxt);
No newline at end of file
+void cmdterm(Cmdctxt *ctxt);
+
+/* cfg.c */
+int cfginit(void);
+void cfgterm(void);
+int cfginsert(Tok *argv, int argc);
+int cfgset(Tok *argv, int argc);
+int cfgdraw(Tok *argv, int argc);
M sky/cmd/lex.c +2 -1
@@ 5,6 5,7 @@
#include "debug.h"
#include "lex.h"
+#include "sky.h"
#include "dat.h"
#include "fns.h"
@@ 71,7 72,7 @@ scmd(Lexer *l, void *aux)
return nxt;
}
- lacceptuntil(l, L" \t\n");
+ lacceptuntil(l, L" \t\n;");
if((len = llen(l)) < 0){
nxt.fun = &serror;
M sky/cmd/mkfile +5 -3
@@ 1,13 1,15 @@
</$objtype/mkfile
-TARG=test_lex test_cmd
+TARG=skywatch
INCDIR=../include
CFLAGS=-I$INCDIR
-LIB=../liblex/liblex.a
+LIB=../libgfx/libgfx.a ../liblex/liblex.a ../libsky/libsky.a
OFILES=\
+ skywatch.$O\
+ cfg.$O\
cmd.$O\
lex.$O\
@@ 20,4 22,4 @@ UPDATE=\
$HFILES\
${OFILES:%.$O=%.c}\
-</sys/src/cmd/mkmany
+</sys/src/cmd/mkone
A sky/cmd/skywatch.c +128 -0
@@ 0,0 1,128 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include <thread.h>
+#include <draw.h>
+
+#include "lex.h"
+#include "sky.h"
+#include "gfx.h"
+
+#include "dat.h"
+#include "fns.h"
+
+enum
+{
+ STACK = 512*1024,
+};
+
+Cmdctxt *cmdctxt;
+
+void cleanup(void);
+void drawscreen(void);
+
+int opquit(Tok *argv, int argc);
+int opredraw(Tok *argv, int argc);
+
+int
+opquit(Tok *argv, int argc)
+{
+ cleanup();
+ threadexitsall(nil);
+
+ return 0;
+}
+
+int
+opredraw(Tok *argv, int argc)
+{
+ drawscreen();
+ return cfgdraw(argv, argc);
+}
+
+void
+drawscreen(void)
+{
+ if(getwindow(display, Refnone) < 0)
+ sysfatal("can't reattach to window");
+
+ print("skywatch.c:resized: %d, %d\n", cfg->camera.wpx, cfg->camera.hpx);
+ resize(cfg->camera.wpx, cfg->camera.hpx);
+
+ draw(screen, screen->r, display->black, nil, ZP);
+ flushimage(display, 1);
+}
+
+void
+init(void)
+{
+ Cmd c;
+
+ if(cfginit() < 0)
+ sysfatal("can't init config");
+
+ if((cmdctxt = mkcmdctxt(0)) == nil)
+ sysfatal("out of memory");
+
+ runestrcpy(c.str, L"insert");
+ c.argc = 1;
+ c.argtyp[0] = Tidentifier;
+ c.fun = &cfginsert;
+ if(cmdreg(cmdctxt, &c) < 0)
+ sysfatal("can't register command");
+
+ runestrcpy(c.str, L"set");
+ c.argc = 2;
+ c.argtyp[0] = Tidentifier;
+ c.argtyp[1] = Tdecimal;
+ c.fun = &cfgset;
+ if(cmdreg(cmdctxt, &c) < 0)
+ sysfatal("can't register command");
+
+ runestrcpy(c.str, L"set");
+ c.argc = 2;
+ c.argtyp[0] = Tidentifier;
+ c.argtyp[1] = Tstr;
+ c.fun = &cfgset;
+ if(cmdreg(cmdctxt, &c) < 0)
+ sysfatal("can't register command");
+
+ runestrcpy(c.str, L"draw");
+ c.argc = 0;
+ c.fun = &opredraw;
+ if(cmdreg(cmdctxt, &c) < 0)
+ sysfatal("can't register command");
+
+ runestrcpy(c.str, L"bye");
+ c.argc = 0;
+ c.fun = &opquit;
+ if(cmdreg(cmdctxt, &c) < 0)
+ sysfatal("can't register command");
+}
+
+void
+cleanup(void)
+{
+ fprint(2, "cleaning up...\n");
+ cmdterm(cmdctxt);
+ cfgterm();
+}
+
+void
+threadmain(int argc, char *argv[])
+{
+ int rm;
+
+ init();
+
+ if(newwindow(nil) < 0 || initdraw(nil, nil, "skywatch") < 0 || gfxinit() < 0)
+ sysfatal("failed to initialise draw: %r");
+
+ drawscreen();
+
+ proccreate(&cmdproc, cmdctxt, STACK);
+
+ for(;;);
+}
+
+
M sky/include/debug.h +1 -1
@@ 1,5 1,5 @@
#ifndef DEBUG_LEVEL
-#define DEBUG_LEVEL 0
+#define DEBUG_LEVEL 10
#endif
#define DBIF(l) if((l)<=DEBUG_LEVEL)
A => sky/include/gfx.h +30 -0
@@ 0,0 1,30 @@
+typedef union RGBi RGBi;
+
+enum
+{
+ Gunsupported = -10,
+ Gfailed = -1,
+};
+
+enum
+{
+ Msquare = 0,
+ Mdisc,
+ Mdiamond,
+ Mplus,
+ Mcross,
+};
+
+union RGBi
+{
+ struct{
+ uchar b, g, r;
+ };
+ uchar buf[3];
+};
+
+int gfxinit(void);
+void gfxterm(void);
+
+void resize(int w, int h);
+int marker(Image *dst, Point pt, RGBi c, int size, int mark, Rune *s);
M sky/include/sky.h +7 -6
@@ 1,5 1,3 @@
-#pragma lib "libsky.a"
-
typedef struct Gdloc Gdloc;
typedef struct Eqloc Eqloc;
typedef struct Hzloc Hzloc;
@@ 67,6 65,9 @@ struct Camera
Viewangle angle;
};
+extern Obs defaultObs;
+extern Camera defaultCamera;
+
#define TWOPI (PI+PI)
#define DEG 1.745329251994329576923e-2
#define DMIN 2.908882086657215961539e-4
@@ 79,10 80,10 @@ struct Camera
#define JDX100 36525.0
/* atmospheric conditions for refraction */
-#define STP_kPa 100.0d
-#define STP_K 273.15d
-#define NTP_kPa 101.325d
-#define NTP_K 293.15d
+#define STP_kPa 100.0
+#define STP_K 273.15
+#define NTP_kPa 101.325
+#define NTP_K 293.15
Eqloc gx2eq00(Gxloc gx);
A => sky/libgfx/gfx.c +80 -0
@@ 0,0 1,80 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+
+#include "gfx.h"
+
+Image *pen = nil;
+
+int setpen(RGBi c);
+
+int
+gfxinit(void)
+{
+ if(!pen && (pen = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, 0)) == nil)
+ return Gfailed;
+
+ return 0;
+}
+
+void
+gfxterm(void)
+{
+ if(pen) freeimage(pen);
+}
+
+void
+resize(int w, int h)
+{
+ int fd;
+
+ fd = open("/dev/wctl", OWRITE);
+ if(fd >= 0){
+ fprint(fd, "resize -dx %d -dy %d", w, h);
+ close(fd);
+ }
+}
+
+int
+marker(Image *dst, Point pt, RGBi c, int size, int mark, Rune *s)
+{
+ Point sh[4];
+
+ if(!setpen(c)) return Gfailed;
+
+ switch(mark){
+ case Msquare:
+ line(dst, pt, pt, Endsquare, Endsquare, size, pen, pt);
+ break;
+ case Mdisc:
+ line(dst, pt, pt, Enddisc, Enddisc, size, pen, pt);
+ break;
+ case Mdiamond:
+ sh[0] = addpt(pt, Pt(-size,0));
+ sh[1] = addpt(pt, Pt(0,-size));
+ sh[2] = addpt(pt, Pt(size,0));
+ sh[3] = addpt(pt, Pt(0,size));
+ fillpoly(dst, sh, 4, 0, pen, pt);
+ break;
+ case Mplus:
+ line(dst, addpt(pt, Pt(0, -size)), addpt(pt, Pt(0, size)), Endsquare, Endsquare, 1, pen, pt);
+ line(dst, addpt(pt, Pt(-size, 0)), addpt(pt, Pt(size, 0)), Endsquare, Endsquare, 1, pen, pt);
+ break;
+ case Mcross:
+ line(dst, addpt(pt, Pt(-size, -size)), addpt(pt, Pt(size, size)), Endsquare, Endsquare, 1, pen, pt);
+ line(dst, addpt(pt, Pt(-size, size)), addpt(pt, Pt(size, -size)), Endsquare, Endsquare, 1, pen, pt);
+ break;
+ default:
+ return Gunsupported;
+ }
+
+ if(s) runestring(dst, addpt(pt, Pt(size+1, size+1)), pen, pt, font, s);
+
+ return 0;
+}
+
+int
+setpen(RGBi c)
+{
+ return loadimage(pen, pen->r, c.buf, 3);
+}
A => sky/libgfx/mkfile +20 -0
@@ 0,0 1,20 @@
+</$objtype/mkfile
+
+LIB=libgfx.a
+
+INCDIR=../include
+
+CFLAGS=-I$INCDIR
+
+OFILES=\
+ ${LIB:lib%.a=%.$O}\
+
+HFILES=\
+ $INCDIR/${LIB:lib%.a=%.h}\
+
+UPDATE=\
+ mkfile\
+ $HFILES\
+ ${OFILES:%.$O=%.c}
+
+</sys/src/cmd/mklib
No newline at end of file
M sky/libsky/sky.c +21 -3
@@ 3,15 3,33 @@
#include "sky.h"
+// Munich, Germany
+Obs defaultObs = {
+ {degms2rad(48, 8, 14.74), degms2rad(11, 34, 31.76), 524.0,},
+ NTP_kPa,
+ NTP_K,
+ 0,
+};
+
+// Canon EOS 600D with a 24mm lens
+Camera defaultCamera = {
+ 24.0,
+ 22.3,
+ 14.9,
+ 5344,
+ 3516,
+ {0, 0, 0,},
+};
+
+double _sdG = 0;
+double _cdG = 0;
+
double gammab_fw(double jd, double dut1, double dt);
double phib_fw(double jd, double dut1, double dt);
double psib_fw(double jd, double dut1, double dt);
double epsA_fw(double jd, double dut1, double dt);
void sXY(double jd, double dut1, double dt, double *s, double *X, double *Y);
-double _sdG = 0;
-double _cdG = 0;
-
Eqloc
gx2eq00(Gxloc gx)
{