Compare commits

...

32 commits

Author SHA1 Message Date
Stephan I. Böttcher
05b0206105 Merge branch 'master' of forge.bexus.org:Stephan/irena-arm 2025-02-24 15:37:06 +01:00
stephan
fef4a9db28 flash_NMAHEPAM: cron with dorn HK and I²C
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9276 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-24 14:36:00 +00:00
stephan
dbf3725f04 nmahepam: aenable(), /hk1
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9275 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-24 14:34:01 +00:00
stephan
fba73eb689 dorn.py: φ⁴ banana and other fixes
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9274 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-24 14:33:00 +00:00
stephan
7c711fd1d8 AHEPAM: φ⁴ banana
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9273 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-24 14:32:02 +00:00
stephan
d623ed3885 ahepam/Makefile: %.hist use onboard E
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9272 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-24 14:31:17 +00:00
stephan
dc0e4e4a27 nmahepam_channels: add column dorn
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9271 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-24 14:30:18 +00:00
stephan
455a33a397 arm: parse_expression_square(…, optional) enhancements
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9270 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-23 23:18:16 +00:00
stephan
cec68e93b9 arm: i2c command
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9269 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-23 21:03:51 +00:00
stephan
9809041577 arm: add command dorn/
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9268 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-23 00:11:56 +00:00
stephan
2e96ff3d73 AHEMAP.awk: fixes
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9266 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-22 10:48:03 +00:00
stephan
704a7c2c78 move nmahepam_channesl.md
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9259 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-17 14:48:04 +00:00
stephan
2fc61dc128 AHEPAM.awk: nmahepam analysis
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9258 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-17 14:37:41 +00:00
stephan
e7c0fd4156 ahepamfile: option for channels per slice
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9253 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-14 21:32:24 +00:00
stephan
6bd5cd06ae NMAHEPAM/CRON: read dorn HK
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9252 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-14 21:31:03 +00:00
stephan
8d7284fc75 dorn write_l2(): fix ch address bit location.
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9251 bc5caf13-1734-44f8-af43-603852e9ee25
2025-02-14 21:25:38 +00:00
stephan
b293536817 nmahepam: hk() updates
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9233 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-28 14:43:20 +00:00
stephan
62bdcf72b7 nmahepam: bitfile
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9232 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-28 14:40:44 +00:00
ava
36a5767824 ADD list for shaper channels through all connectors
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9230 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-28 13:40:41 +00:00
ava
37e18dd984 nmahepam.py: ADD further channels to hk()
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9211 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-15 12:56:01 +00:00
stephan
f01cc2f807 nmahepam: HK channels 4.)
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9206 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-09 09:47:19 +00:00
ava
825eea0422 Add table of channels: nmahepam_channels.md
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9205 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-08 16:23:10 +00:00
stephan
ecc3dc3742 nmahepam: fixes, mv hk()
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9204 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-07 12:57:14 +00:00
ava
d41bfa309a ADD nmahepam.py as copy of nmrena.py
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9203 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-07 11:17:12 +00:00
stephan
222aad1e90 dorn.py: fixes and CONFIG rename
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9202 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-07 00:16:59 +00:00
stephan
83ac07f0ce IRENA: isCHAOS_SP()
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9201 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-07 00:12:59 +00:00
stephan
a6955e771f mainloop: print revision as hex @ boot
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9200 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-06 22:57:42 +00:00
stephan
a0f7f831cb CHAOS CRON.RC: HK schedule as in FLY
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9199 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-06 22:57:37 +00:00
stephan
9a58fdff52 .gitignore operational files
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9198 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-06 22:50:13 +00:00
stephan
3f285a00b7 dorn.py: separated out of narena.py
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9197 bc5caf13-1734-44f8-af43-603852e9ee25
2025-01-06 22:28:21 +00:00
stephan
55d797b13f rsync from hfsjg via jumphost cosray
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9185 bc5caf13-1734-44f8-af43-603852e9ee25
2024-12-23 16:49:33 +00:00
stephan
4cfc59dbe9 rsync from bern via jumphost cosray
git-svn-id: svn+ssh://asterix.ieap.uni-kiel.de/home/subversion/stephan/solo/eda/arm@9184 bc5caf13-1734-44f8-af43-603852e9ee25
2024-12-23 11:35:06 +00:00
26 changed files with 879 additions and 212 deletions

5
.gitignore vendored
View file

@ -4,9 +4,12 @@ irena.bin
irena.hex irena.hex
irena.rom* irena.rom*
revision.h revision.h
*.fat *.fat*
__pycache__ __pycache__
revision.h+ revision.h+
*~ *~
*.s *.s
oops.txt oops.txt
irenarc.py
irenafile
*/data

View file

@ -146,7 +146,7 @@ sources = irena mainloop parser message isr crc \
enc28j60 net udp \ enc28j60 net udp \
expression variables display \ expression variables display \
adc rtc hk \ adc rtc hk \
plugin pressure gps chaos \ plugin pressure gps chaos dorn i2c \
nomalloc strtol uart base85 nomalloc strtol uart base85
$(NAME).rom: lpc2148-rom.ld $(OBJS) $(NAME).rom: lpc2148-rom.ld $(OBJS)

View file

@ -2,7 +2,7 @@
function isE(d,c) { function isE(d,c) {
if (!/^ED/ || $3!=d || $4!=c) return 0 if (!/^ED/ || $3!=d || $4!=c) return 0
Ch=d*3+c Ch = NDCh * d + c
T0 = $2 T0 = $2
A = $7/1024 A = $7/1024
B=$8/1024 B=$8/1024
@ -14,6 +14,94 @@ function isE(d,c) {
return 1 return 1
} }
function isEE() {
if (!/^ED/) return 0
d = $3
c = $4
Ch = NDCh * d + c
T0 = $2
A = $7/1024
B=$8/1024
P=$9/0x4000
Ba=$10/0x4000
E=$11/0x20000
EE=A*BANANA(d,c, P)
N = 0
return 1
}
function isCC() {
N = 0
if (!/^ED /) return 0
if (NE && ($2 > T0+20 || $2+20 < T0)) {
N = NE
TE0 = T0
save = $0
delete TT
delete AA
delete PP
delete HH
delete EE
for (i=0; i<NCh; i++) {
if (i in ELINES) {
$0 = ELINES[i]
TT[i] = $2-TE0
AA[i] = $7/1024
PP[i] = $9/0x4000
HH[i] = Phase(PP[i])
EE[i] = $11/0x20000
}
}
NE = 0
delete ELINES
$0 = save
}
if (!NE) T0 = $2
i = NDCh * $3 + $4
ELINES[i] = $0
NE++
if (N) {
if (TE0 < 0x40000000 && TLAST > 0xc0000000) EPOCH += 0x100000000
TLAST = TE0
}
return N
}
function doCC() {
printf "%.0f %d", TE0+EPOCH, N
for (i=0; i<NCh; i++)
printf " %d:%.3f:%.3f:%.2f:%.2f", \
TT[i], PP[i], HH[i], AA[i], EE[i]
printf "\n"
}
function doCCC() {
printf "%.0f %d", TE0+EPOCH, N
for (i=0; i<NCh; i++)
if (i in AA)
printf " %d:%.3f:%.3f:%.2f:%.2f", \
TT[i], PP[i], HH[i], AA[i], EE[i]
else
printf " :"
printf "\n"
}
BEGIN { CCcut = 10 }
function doCC2() {
if (N<2) return
for (i=0; i<NCh; i++)
if (EE[i]>5)
for (j=i+1; j<NCh; j++)
if (EE[j] > CCcut) {
ii = int(i/8)
jj = int(j/8)
printf "%.0f %d %d %d %d %d %d %.3f %.3f %.3f %.3f %.1f %.1f\n", \
TE0+EPOCH, i, j, ii, jj, \
TT[i], TT[j], PP[i], PP[j], HH[i], HH[j], EE[i], EE[j]
}
}
function is2D(d1, c1, d2, c2, delta) { function is2D(d1, c1, d2, c2, delta) {
r = 0 r = 0
delta++ delta++
@ -91,19 +179,56 @@ function isS2(d1,c1,d2,c2) {
SS2 = S2-S20 SS2 = S2-S20
return N return N
} }
function isS(d,c) {
if (isE(d,c)) ELINE=$0 BEGIN {
if (!/^SD/ || $2<T0 || $2>T0+32) return 0 doScut=10
S = $(3+8*c+d) }
T = $2
TT = T-T0 + Phase(P) function doS() {
if (!N) { N = 0
T1=TT if (!/[SE]D /) return N
S0 = 0 if (NS && ($2 > TS0+20 || $2 < TS0-20)) {
save = $0
for (d in ELINES) {
for (c in ELINES[d]) {
$0 = ELINES[d][c]
E = $11/0x20000
if (E <= doScut) continue
T0 = $2
A = $7/1024
B = $8/1024
P = $9/0x4000
Ba = $10/0x4000
n0 = 0
S0 = 0
for (i = T0-2; i <= T0+2; i++)
if (i in SLINES[d]) {
$0 = SLINES[d][i]
n0++;
S0 += $(4+c)
}
if (n0)
S0 /= n0
for (i in SLINES[d]) {
$0 = SLINES[d][i]
if ($2 > T0+40 || $2 < T0-20) continue
print d, c, T0, A, P, Phase(P), E, $2-T0, S0, $(4+c), ($(4+c)-S0)/E
}
N++
}
}
delete ELINES
delete SLINES
NS = 0
$0 = save
} }
N++ if (/^ED/) {
if (N==1 || TT<3.5) S0=((N-1)*S0 + S)/N ELINES[$3][$4] = $0
SS = S-S0 return N
}
if (!NS) TS0 = $2
SLINES[$3][$2] = $0
NS++
return N return N
} }
@ -111,6 +236,16 @@ BEGIN {
ph0 = -0.535102 ph0 = -0.535102
ph1 = 1.83084 ph1 = 1.83084
ph2 = -0.171461 ph2 = -0.171461
# 2025-02-14-nmahepam-l2fixed-6
ph0 = -0.51035
ph1 = 1.88779
ph2 = 0
# 2025-02-20-seth-pa1-2
ph0 = -0.505601 # ± 3.072e-05
ph1 = 1.94725 # ± 0.00051
ph2 = -0.139787 # ± 0.0009408
} }
function Phase(P) { function Phase(P) {
@ -128,10 +263,14 @@ function doHIST(Ch, x) {
BEGIN { BEGIN {
NCh=12 NCh=12
for (i=0; i<NCh;i++) name[i] = substr("CBAFEDIHGLKJ",i+1,1) for (i=0; i<NCh; i++) name[i] = substr("CBAFEDIHGLKJ",i+1,1)
minV=-100 minV=-100
maxV=5000 maxV=5000
resV=0.25 resV=0.25
# AHEPAM BGO slice 1 only:
NCh = 24
NDCh = 0
for (i=0; i<NCh; i++) name[i] = "1:" i
} }
function print_HIST(fn) { function print_HIST(fn) {
@ -153,28 +292,6 @@ function print_HIST(fn) {
END { if (haveHIST) print_HIST("/dev/stdout") } END { if (haveHIST) print_HIST("/dev/stdout") }
BEGIN { BEGIN {
# iterated F-banana
b0 = -0.24534 # +/- 0.0009303 (0.3792%)
b2 = 0.787721 # +/- 0.004091 (0.5194%)
b3 = -0.144295 # +/- 0.02664 (18.46%)
# 2022-03-13-aha-bi207-18 LM
b0 = -0.244794 # +/- 0.001249 (0.5104%)
b2 = 0.77673 # +/- 0.005407 (0.6962%)
b3 = -0.12307 # +/- 0.03541 (28.77%)
# 2022-03-13-aha-bi207-18 K
b0 = -0.245065 # +/- 0.0006364 (0.2597%)
b2 = 0.779905 # +/- 0.002807 (0.3599%)
b3 = -0.113925 # +/- 0.01827 (16.03%)
for (d=0;d<8;d++) for (c=0;c<3;c++) {
B0[d,c] = b0
B2[d,c] = b2
B3[d,c] = b3
}
# B # B
B0[0,1] = -3709 / 16384 B0[0,1] = -3709 / 16384
@ -192,9 +309,45 @@ BEGIN {
B0[3,2] = -3802 / 16384 B0[3,2] = -3802 / 16384
B2[3,2] = 14943 / 16384 B2[3,2] = 14943 / 16384
B3[3,2] = 4596 / 32768 B3[3,2] = 4596 / 32768
# iterated F-banana
b0 = -0.24534 # +/- 0.0009303 (0.3792%)
b2 = 0.787721 # +/- 0.004091 (0.5194%)
b3 = -0.144295 # +/- 0.02664 (18.46%)
# 2022-03-13-aha-bi207-18 LM
b0 = -0.244794 # +/- 0.001249 (0.5104%)
b2 = 0.77673 # +/- 0.005407 (0.6962%)
b3 = -0.12307 # +/- 0.03541 (28.77%)
# 2022-03-13-aha-bi207-18 K
b0 = -0.245065 # +/- 0.0006364 (0.2597%)
b2 = 0.779905 # +/- 0.002807 (0.3599%)
b3 = -0.113925 # +/- 0.01827 (16.03%)
b4 = 0
for (d=0;d<8;d++) for (c=0;c<24;c++) {
B0[d,c] = b0
B2[d,c] = b2
B3[d,c] = b3
B4[d,c] = b4
}
# 2025-02-20-seth-pa1-4
# integer fit: -3839 /2¹⁴, 13891 /2¹⁴, 3579 /2¹⁶, 22853 /2¹⁶,
for (d=0;d<8;d++) for (c=0;c<24;c++) {
# full fit
B0[d,c] = -0.234334699085823
B2[d,c] = 0.84786326376432
B3[d,c] = 0.10845413271095
B4[d,c] = 0.696742143682933
}
} }
function BANANA(d,c, p) { function BANANA(d,c, p) {
p -= B0[d,c] p -= B0[d,c]
return 1+p*p*(B2[d,c] + p*B3[d,c]) return 1+p*p*(B2[d,c] + p*(B3[d,c] + p*B4[d,c]))
} }

View file

@ -5,6 +5,9 @@ include ../irena/libirena.make
%.AHA: %.dat ahepamfile %.AHA: %.dat ahepamfile
./ahepamfile < $< > $@ ./ahepamfile < $< > $@
%.doS: %.AHA
./AHEPAM.awk 'doS(){}' $< > $@
%.AES: %.dat ahepamfile %.AES: %.dat ahepamfile
./ahepamfile < $< | grep '^[ES]' | grep -v 'X' | sort -nk2,2 -k1 > $@ ./ahepamfile < $< | grep '^[ES]' | grep -v 'X' | sort -nk2,2 -k1 > $@
@ -31,7 +34,7 @@ SIGMA=600
resV=1 resV=1
%.hist: %.AHA %.hist: %.AHA
./AHEPAM.awk 'isE($$3,$$4){doHIST(Ch,EE)}' resV=$(resV) $< > $@ ./AHEPAM.awk 'isEE(){doHIST(Ch,E)}' resV=$(resV) $< > $@
CUT=P CUT=P
CUT_P=&&P>-0.398&&P<=-0.105 CUT_P=&&P>-0.398&&P<=-0.105

View file

@ -62,9 +62,9 @@ static inline int dorn_event(unsigned int h1, unsigned int n, int stis)
if (banana & 0x8000) banana |= 0xffff0000; if (banana & 0x8000) banana |= 0xffff0000;
unsigned int ch = (det >> nn) & 3; unsigned int ch = (det >> nn) & 3;
unsigned int lost = det >> (nn+2); unsigned int lost = det >> (nn+2);
det &= 7; det &= n-1;
if (stis) { if (stis) {
ch = ch*4 + (det & 3); ch = (ch<<nn) | det;
det = h1 & 3; det = h1 & 3;
} }
printf("\nED %u %u %u %d %u %d %d %d %d %d", clock, det, ch, dtime, lost, a, b, phase, banana, pha); printf("\nED %u %u %u %d %u %d %d %d %d %d", clock, det, ch, dtime, lost, a, b, phase, banana, pha);
@ -109,9 +109,9 @@ int main(int argc, const char * const * argv)
case 0xd1e7: x = dorn_event(h1, n_counters, 0); break; case 0xd1e7: x = dorn_event(h1, n_counters, 0); break;
default: default:
switch (h1 & 0xfffc) { switch (h1 & 0xfffc) {
case 0x5710: x = dorn_hk(h1, 4, 1); break; case 0x5710: x = dorn_hk(h1, n_counters, 1); break;
case 0x5714: x = dorn_samples(h1, 4, 1); break; case 0x5714: x = dorn_samples(h1, n_counters, 1); break;
case 0x5718: x = dorn_event(h1, 4, 1); break; case 0x5718: x = dorn_event(h1, n_counters, 1); break;
default: default:
if (!x || x>32) { if (!x || x>32) {
printf("\nX %04x", h1); printf("\nX %04x", h1);

View file

@ -0,0 +1,41 @@
| | A | B | C | D | E | F | G | H
---------------------------------------------------------------------------
0 | shaper | 02 | 05 | 08 | 11 | 15 | 16 | 21 | 22
1 | shaper | 01 | 04 | 07 | 10 | 12 | 17 | 18 | 23
2 | shaper | 00 | 03 | 06 | 09 | 13 | 14 | 19 | 20
3 | monitor | Ibias | Vff | Vnn | Vpp | Vdig | NTC | Vcc | Vss
4 | monitor | EXT,NTC | NTC | Bias | REF,NTC | Bias1 | Bias2 | Vss | Vcc
5 | VrefL | | | | | | | |
6 | Vref | | | | | | | |
7 | mon[A-H] | | | | | | | |
connector | channel (PIN) | shaper | CONN1 | ADC | data | dorn
CONN10 | 1 (13) | 00 | 20 | A0 | [2][0] | 16
CONN10 | 2 (12) | 01 | 60 | A1 | [1][0] | 8
CONN10 | 3 (11) | 02 | 19 | A2 | [0][0] | 0
CONN10 | 4 (10) | 03 | 59 | B0 | [2][1] | 17
CONN10 | 5 (9) | 04 | 18 | B1 | [1][1] | 9
CONN10 | 6 (8) | 05 | 58 | B2 | [0][1] | 1
CONN10 | 7 (7) | 06 | 16 | C0 | [2][2] | 18
CONN10 | 8 (6) | 07 | 56 | C1 | [1][2] | 10
-----------------------------------------------------------------
CONN11 | 1 (13) | 08 | 18 | C2 | [0][2] | 2
CONN11 | 2 (12) | 09 | 55 | D0 | [2][3] | 19
CONN11 | 3 (11) | 10 | 14 | D1 | [1][3] | 11
CONN11 | 4 (10) | 11 | 54 | D2 | [0][3] | 3
CONN11 | 5 (9) | 12 | 52 | E1 | [1][4] | 12
CONN11 | 6 (8) | 13 | 12 | E0 | [2][4] | 20
CONN11 | 7 (7) | 14 | 51 | F0 | [2][5] | 21
CONN11 | 8 (6) | 15 | 11 | E2 | [0][4] | 4
-----------------------------------------------------------------
CONN12 | 1 (13) | 16 | 50 | F2 | [0][5] | 5
CONN12 | 2 (12) | 17 | 10 | F1 | [1][5] | 13
CONN12 | 3 (11) | 18 | 48 | G1 | [1][6] | 14
CONN12 | 4 (10) | 19 | 8 | G0 | [2][6] | 22
CONN12 | 5 (9) | 20 | 47 | H0 | [2][7] | 23
CONN12 | 6 (8) | 21 | 7 | G2 | [0][6] | 6
CONN12 | 7 (7) | 22 | 46 | H2 | [0][7] | 7
CONN12 | 8 (6) | 23 | 6 | H1 | [1][7] | 15

View file

@ -134,7 +134,7 @@ static error_msg_t parse_secondary(struct command *cmd, const struct command_par
if (!e && kw) { if (!e && kw) {
*sec = kw->val; *sec = kw->val;
if (kw->val==2) if (kw->val==2)
e = parse_expression_square(cmd, &psconfig2, 2); e = parse_expression_square(cmd, &psconfig2, optional_brackets);
} }
return e; return e;
} }

View file

@ -88,14 +88,14 @@ static int chaos_adc(struct command *cmd, const struct command_par *par)
int c = par->code; int c = par->code;
unsigned int what = (unsigned int)par->par; unsigned int what = (unsigned int)par->par;
unsigned int v = what; unsigned int v = what;
error_msg_t e = parse_expression_square(cmd, &v, 3); error_msg_t e = parse_expression_square(cmd, &v, optional_number|optional_close);
if (e) if (e)
return parser_error_message(cmd, e); return parser_error_message(cmd, e);
unsigned char chs = v; unsigned char chs = v;
if (!chs) if (!chs)
chs = 0xff; chs = 0xff;
unsigned char rep = (v>>8) & 0xf; unsigned char rep = (v>>8) & 0xf;
if (!parse_expression_square(cmd, &v, 0)) if (!parse_expression_square(cmd, &v, optional_open))
rep = v; rep = v;
if (what & 0x01000000) { if (what & 0x01000000) {
if (ads8688_results(chs)) if (ads8688_results(chs))

105
dorn.c Normal file
View file

@ -0,0 +1,105 @@
#include "dorn.h"
#include "altera.h"
static const struct keywords dorn_fifo_kw[] = {
{"read", {.par= ALT_CMD_AF( 0) }},
{"empty", {.par= ALT_CMD_AF( 4) }},
{"packet", {.par= ALT_CMD_AF( 5) }},
{"full", {.par= ALT_CMD_AF( 6) }},
{"enable", {.par= ALT_CMD_AF( 7) }},
{"hbase", {.par= ALT_CMD_AF( 8) }},
{"strobe", {.par= ALT_CMD_AF(11) }},
{"mwrite", {.par= ALT_CMD_AF(12) }},
{"mdata", {.par= ALT_CMD_AF(13) }},
{"maddr", {.par= ALT_CMD_AF(14) }},
{"mnext", {.par= ALT_CMD_AF(15) }},
KW_END
};
int dorn_fifo(struct command *cmd, const struct command_par *par)
{
return altera_set_register(cmd, par, dorn_fifo_kw, 0,
(unsigned int)par->par, "fifo");
}
static const struct keywords dorn_trigger_kw[] = {
{"t1", {.par= ALT_CMD_AF( 8) }},
{"t2", {.par= ALT_CMD_AF( 9) }},
{"t3", {.par= ALT_CMD_AF(10) }},
{"samples", {.par= ALT_CMD_AF(11) }},
{"atrigger", {.par= ALT_CMD_AF( 8 | alt_cmd_double) }},
{"cwin", {.par= ALT_CMD_AF(12) }},
{"bin0", {.par= ALT_CMD_AF(13) }},
KW_END
};
int dorn_trigger(struct command *cmd, const struct command_par *par)
{
unsigned int a = (unsigned int)par->par;
error_msg_t e = parse_index(cmd, &a, 3, 11, 1);
if (e)
return parser_error_message(cmd, e);
return altera_set_register(cmd, par, dorn_trigger_kw, 0, a, "trigger");
}
static
error_msg_t parse_channel(struct command *cmd, unsigned int *a, int c, int m, int b)
{
error_msg_t e = parse_index(cmd, a, 3, 11, 1);
if (!e)
e = parse_index(cmd, a, 63, c, 2);
if (!e && m)
e = parse_index(cmd, a, m, b, 2);
return e;
}
int dorn_l1(struct command *cmd, const struct command_par *par)
{
unsigned int a = (unsigned int)par->par;
error_msg_t e = parse_channel(cmd, &a, 0, 0, 0);
if (e)
return parser_error_message(cmd, e);
return altera_set_register(cmd, par, 0, alt_cmd_inj, a, "thres");
}
static const
struct keywords dorn_l2_kw[] = {
{"a", {.par= ALT_CMD_AF( 0) }},
{"b", {.par= ALT_CMD_AF( 1) }},
KW_END
};
int dorn_l2(struct command *cmd, const struct command_par *par)
{
unsigned int a = (unsigned int)par->par;
error_msg_t e = parse_channel(cmd, &a, 4, 7, 1);
if (e)
return parser_error_message(cmd, e);
return altera_set_register(cmd, par, dorn_l2_kw, alt_cmd_inj, a, "filter");
}
int dorn_l3(struct command *cmd, const struct command_par *par)
{
unsigned int a = (unsigned int)par->par;
error_msg_t e = parse_channel(cmd, &a, 2, 3, 0);
if (e)
return parser_error_message(cmd, e);
return altera_set_register(cmd, par, 0, alt_cmd_inj, a, "banana");
}
static const struct keywords dorn_commands[] = {
CMD_KW("fifo", dorn_fifo, 255, (void*)(0xa080)),
CMD_KW("enable", dorn_trigger, 255, (void*)(0xa008)),
CMD_KW("thres", dorn_l1, 255, (void*)(0xa040)),
CMD_KW("l1", dorn_l1, 255, (void*)(0xa040)),
CMD_KW("filter", dorn_l2, 255, (void*)(0xa400)),
CMD_KW("l2", dorn_l2, 255, (void*)(0xa400)),
CMD_KW("a", dorn_l2, 255, (void*)(0xa400)),
CMD_KW("b", dorn_l2, 255, (void*)(0xa401)),
CMD_KW("banana", dorn_l3, 255, (void*)(0xa100)),
CMD_KW("l3", dorn_l3, 255, (void*)(0xa100)),
{"", {.par=&parser_unknown_command}}
};
COMMAND(dorn_command, parse_sub_command, 909, dorn_commands);

2
dorn.h Normal file
View file

@ -0,0 +1,2 @@
#include "parser.h"
extern const struct command_par dorn_command;

218
dorn.py
View file

@ -1,46 +1,70 @@
import math import math, time, sys
AHEPAM_CONFIG = { def _connect(ifc):
dorn_addr: 0x2000, global _ifc, ecmd
verbose: True, _ifc = ifc
slices: (0,1), ecmd = ifc.ecmd
n_channels: 24
}
def dorn_config(a, v=None, m=None, slice=0): class DORN_CONFIG:
verb = AHEPAM_CONFIG.verbose # stis_ana_core 2×24 ch
a |= AHEPAM_CONFIG.dorn_addr | (slice<<11) dorn_addr = 0x2000
a &= 0xfff verbose = True
slices = (0,1)
n_channels = 24
l2 = ( # set6
(0, -1203, 0),
(1, -1203, 0),
(2, -1203, 0),
(3, -1186, 0),
(4, -39, 2000),
(5, 1709, 970),
(6, 2000, -1082),
(7, 1125, -1888),
)
def n_adc(self):
return self.n_channels//3
def Vref(self, slice=None):
try:
return self.VREF[slice]
except:
pass
return 3.3
def n_trigs(self):
if self.n_channels > 16:
return self.n_adc()
return self.n_channels
def m_trigs(self):
return (1 << self.n_trigs()) - 1
NTC = [dict(R1=10e3, R25=10e3, B25=3940, res=0x1000)]
CONFIG = DORN_CONFIG()
def dorn_config(a, v=None, mes=None, slice=0):
verb = CONFIG.verbose
a |= CONFIG.dorn_addr | (slice<<11)
if v is None: if v is None:
if not m: if not mes:
m = f"dorn[0x{a:03x}]" mes = f"dorn[0x{a:03x}]"
return int(ecmd(f"alt/cmd/del[10] 0x{a:03x}", task=m, verb=verb).split()[-1], 0) return int(ecmd(f"alt/cmd/del[10] 0x{a:03x}", task=mes, verb=verb).split()[-1], 0)
if not m: if not mes:
m = f"dorn[0x{a:03x}] = 0x{v:04x}" mes = f"dorn[0x{a:03x}] = 0x{v:04x}"
if v is False: if v is False:
ecmd(f"alt/cmd/inj/del[1] 0x{a:03x}", task=m, verb=verb) ecmd(f"alt/cmd/inj/del[1] 0x{a:03x}", task=mes, verb=verb)
else: else:
ecmd(f"alt/cmd/inj/del[1] 0x{a:03x} 0x{v:04x}", task=m, verb=verb) ecmd(f"alt/cmd/inj/del[1] 0x{a:03x} 0x{v:04x}", task=mes, verb=verb)
def thres(sl, ch, v): def thres(sl, ch, v):
dorn_config(0x040 | ch, v, slice=sl) dorn_config(0x040 | ch, v, slice=sl)
def write_l2(sl, ch, i, a, b): def write_l2(sl, ch, i, a, b):
dorn_config(0x400 | (ch<<3) | (i<<1) | 0, a & 0xffff, slice=sl) dorn_config(0x400 | (ch<<4) | (i<<1) | 0, a & 0xffff, slice=sl)
dorn_config(0x400 | (ch<<3) | (i<<1) | 1, b & 0xffff, slice=sl) dorn_config(0x400 | (ch<<4) | (i<<1) | 1, b & 0xffff, slice=sl)
l2_set6 = ( def calib_l2(cal, coeff):
(0, -1203, 0),
(1, -1203, 0),
(2, -1203, 0),
(3, -1186, 0),
(4, -39, 2000),
(5, 1709, 970),
(6, 2000, -1082),
(7, 1125, -1888),
)
def calib_l2(cal, l2_set6):
if cal is None: if cal is None:
return coeff return coeff
from numpy import array, floor, add, any from numpy import array, floor, add, any
@ -64,52 +88,60 @@ def calib_l2(cal, l2_set6):
w = e<0 w = e<0
return [(x, int(ii[0]), int(ii[1])) for x, ii in enumerate(i)] return [(x, int(ii[0]), int(ii[1])) for x, ii in enumerate(i)]
def l2filter(coeff=l2_set6, cal=None): def l2filter(coeff=None, cal=None):
for sl in AHEPAM_CONFIG.slices: if coeff==None:
for ch in range(AHEPAM_CONFIG.n_channels): coeff = CONFIG.l2
for sl in CONFIG.slices:
for ch in range(CONFIG.n_channels):
c = coeff c = coeff
if cal and cal[sl] and cal[sl][ch]: if cal and cal[sl] and cal[sl][ch]:
c = calib_l2(cal[sl][ch]) c = calib_l2(cal[sl][ch], c)
for cc in c: for cc in c:
write_l2(sl, ch, *cc) write_l2(sl, ch, *cc)
def write_l3(sl, ch, *p): def write_l3(sl, ch, *p):
scales = (14, 16, 14, 15) scales = (14, 14, 15, 15)
for i,pp in enumerate(p): for i,pp in enumerate(p):
if isinstance(pp, float): if isinstance(pp, float):
pp = int(pp * 2**scales[i]) pp = int(pp * 2**scales[i])
dorn_config(0x100 | (ch<<2) | i, pp & 0xffff, slice=sl) dorn_config(0x100 | (ch<<2) | i, pp & 0xffff, slice=sl)
def l3banana( def l3banana(
# iterated F-banana 2022-03-13-aha-bi207-18, # 2025-02-20-seth-pa1-4
p0 = -4007, p0 = -3839,
p1 = 0, p2 = 13891,
p2 = 12737, p3 = 3579,
p3 = -3698 ): p4 = 22853 ):
for sl in AHEPAM_CONFIG.slices: for sl in CONFIG.slices:
for ch in range(AHEPAM_CONFIG.n_channels): for ch in range(CONFIG.n_channels):
write_l3(sl, ch, p0, p1, p2, p3) write_l3(sl, ch, p0, p2, p3, p4)
def c16log2(A): def c16log2(A):
return int(math.ceil(16*math.log(1024*A)/math.log(2))) return int(math.ceil(16*math.log(1024*A)/math.log(2)))
def enable_trigger(sl, triggers, det=False, sa=False): def enable_trigger(sl, triggers, det=False, sa=False):
i = 2 if sa else 0 if det else 1 i = 2 if sa else 0 if det else 1
dorn_config(0x008 | i | sl<<4, triggers, slice=sl) dorn_config(0x008 | i, triggers, slice=sl)
def nsamples(sl, n=None, m=None, **slice): def nsamples(sl, n=None, m=None, **slice):
if n is None: if n is None:
return dorn_config(0x00b | sl<<4, slice=sl) return dorn_config(0x00b, slice=sl)
if m is None: if m is None:
m = 0xfff if n else 0 m = 0xffff if n else 0
enable_trigger(sl, m, sa=True) enable_trigger(sl, m, sa=True)
dorn_config(0x00b | sl<<4, n, slice=sl) dorn_config(0x00b, n, slice=sl)
def triggers(sl, atrig=0x3ff, dtrig=0, sam=0, nsa=32): def triggers(sl, atrig=0xffff, dtrig=0, sam=0, nsa=10):
enable_trigger(sl, dtrig, det=True) enable_trigger(sl, dtrig, det=True)
enable_trigger(sl, atrig) enable_trigger(sl, atrig)
nsamples(sl, nsa, sam) nsamples(sl, nsa, sam)
def atriggers(sl, atrig=0, gtrig=0, csa=False, gsa=False, nsa=10):
dorn_config(0x008, slice=sl, v=atrig & 0xffff, mes="atrig[15:0]")
dorn_config(0x009, slice=sl, v=(atrig>>16)|((gtrig&0xff)<<8), mes="gtrig[7:0],atrig[23:8]")
dorn_config(0x00a, slice=sl, v=gtrig>>8, mes="gtrig[23:8]")
dorn_config(0x00b, slice=sl, v=(gsa<<9)|(csa<<8)|nsa, mes="nsamples")
def hist_bins(sl, bin0=4.0, res=1, cwin=6, xtalk=6): def hist_bins(sl, bin0=4.0, res=1, cwin=6, xtalk=6):
"""configure dorn_l4 histogramming """configure dorn_l4 histogramming
bin0: float: A-value of bin 0, int: 16LOG2(A) bin0: float: A-value of bin 0, int: 16LOG2(A)
@ -119,8 +151,8 @@ xtalk: x-talk ratio cut: reject if S > (S>>xtalk)
""" """
if isinstance(bin0, float): if isinstance(bin0, float):
bin0=c16log2(bin0) bin0=c16log2(bin0)
dorn_config(0x00c | sl<<4, (xtalk<<8) | cwin) dorn_config(0x00c, (xtalk<<8) | cwin, slice=sl)
dorn_config(0x00d | sl<<4, (res<<9) | bin0) dorn_config(0x00d, (res<<9) | bin0, slice=sl)
def base_address(hists=None, counters=None, hmask=None, cmask=None): def base_address(hists=None, counters=None, hmask=None, cmask=None):
if hists is not None: if hists is not None:
@ -152,17 +184,17 @@ def fifo_select(hi=False, sl=None, hk=False, ev=False, sa=False, i=None):
if sl is not None: if sl is not None:
f <<= 3*sl+1 f <<= 3*sl+1
else: else:
f *= 18 f *= 0b0010010010010
f |= hi f |= hi
return f return f
def fifo_enable(en=False, rfifo=False, sl=None, **aa): def fifo_enable(en=True, rfifo=True, men=True, sl=None, **aa):
f = fifo_select(sl=sl, **aa) f = fifo_select(sl=sl, **aa)
if sl is None and en: if sl is None and en is True:
en = 3 en = 0xf
elif sl is not None: elif sl is not None:
en <<= sl en <<= sl
dorn_config(0x087, (f<<6) | (rfifo<<5) | en) dorn_config(0x087, (f<<6) | (rfifo<<5) | (men<<4) | en)
STROBES = { STROBES = {
"read_fifos": 0, "read_fifos": 0,
@ -205,68 +237,34 @@ def fifo_read(**aa):
else: else:
dorn_config(0x085, f) dorn_config(0x085, f)
def degC(a, R1=10e3, R25=10e3, B25=3750, res=0x1000): def degCβ(a, R1=10e3, R25=10e3, B25=3940, res=0x1000):
R=R1*a/(res-(a&(res-1))) if not a:
return B25/(math.log(R/R25)+B25/298) - 273 a = 1
R = R1 * a / (res - (a & (res-1)))
T = B25/(math.log(R/R25) + B25/298) - 273
return T
#TO DO: Adjust def degC(a, idx=0):
def nmahepam_hk(sl, what="data", data=none, ND=8, NV=8, Vref=3.3): return degCβ(a, **CONFIG.NTC[idx])
if not data:
ecmd("alt/stream/off")
fifo_enable(en=True, sl=sl, hk=True)
fifo_reset(sl=sl, hk=True)
strobe(sl=sl, hk=True)
sleep(0.001)
fifo_read(sl=sl, hk=True)
data=read_fifo()
if (data[0] & 0xfffc) != 0x5710:
raise ValueError("Read HK packet error", data)
if what=="data":
return data
data = [d & 0xfff for d in data]
data = [data[ND*i+1:ND*i+1+NV] for i in range(8)]
if what=="raw":
return data
#NMAHEPAM:data[7][0] *= 2*Vref/4096 # Vcore
data[7][1] = degC(data[7][1]) # Tana
data[7][2] *= 2*Vref/4096 # V+6
data[7][3] *= 2.5*Vref/4096 # V-6
data[7][3] -= 1.5*data[7][2]
data[6][0] *= Vref/4096/0.0206 # Vbias
data[6][1] = degC(data[6][1]) # Tpa
data[6][3] *= 2*Vref/4096 # Vcc
data[6][2] *= 2.5*Vref/4096 # Vss
data[6][2] -= 1.5*data[6][3]
if what=="cooked":
return data
sys.stderr.write("""nmahepam HK:
Vcore = %6.3f V
Tana = %6.2f °C
V+6 = %6.3f V
V-6 = %6.3f V
Vbias = %6.2f V
Tpa = %6.2f °C
Vss = %6.3f V
Vcc = %6.3f V
""" % tuple(data[7]+data[6]))
def default_config(thr=0x7ff): def default_config(thr=0x7ff):
for sl in range(AHEPAM_CONFIG.slices): for sl in CONFIG.slices:
for ch in range(AHEPAM_CONFIG.n_channels): for ch in range(CONFIG.n_channels):
thres(sl, ch, thr) thres(sl, ch, thr)
l2filter() l2filter()
l3banana() l3banana()
for sl in range(AHEPAM_CONFIG.slices): for sl in CONFIG.slices:
hist_bins(sl) atriggers(sl)
triggers(sl, 0)
def print_trigger_config(): def print_trigger_config():
tri = [[dorn_config(0x008 + i + (sl<<4)) for i in range(4)] for sl in range(2)] tri = [[dorn_config(0x008 + i, slice=sl)
for i in range(4)]
for sl in CONFIG.slices]
ff = [dorn_config(0x084+i) for i in range(4)] ff = [dorn_config(0x084+i) for i in range(4)]
tri.append(ff) tri.append(ff)
e = ff[3] e = ff[3]
df = [Areg(0x11+i) for i in range(3)] df = [_ifc.Areg(0x11+i) for i in range(3)]
df.append(Areg(5)) df.append(_ifc.Areg(5))
tri.append(df) tri.append(df)
print(f"""narena trigger config: print(f"""narena trigger config:
trigger detector masks: trigger detector masks:
@ -286,7 +284,7 @@ fifos enable SA/EV/HK HI {(e>>7)&7:03b} {(e>>10)&7:03b} {(e>>6)&1}
def read_event(sl=None, ev=None): def read_event(sl=None, ev=None):
if ev is None: if ev is None:
fifo_read(sl=sl, ev=True) fifo_read(sl=sl, ev=True)
ev = read_fifo(2) ev = ifc._read_fifo(2)
if (ev[0] & 0xfffc) != 0x5718: if (ev[0] & 0xfffc) != 0x5718:
raise ValueError(f"EV packet magic mismatch {ev[0]:04x}") raise ValueError(f"EV packet magic mismatch {ev[0]:04x}")
Ba = ev[5] Ba = ev[5]
@ -326,7 +324,7 @@ def read_samples(sl=0, n=None, sa=None):
if not (ff & (8 << (3*sl))): if not (ff & (8 << (3*sl))):
break; break;
fifo_read(sl=sl, sa=True) fifo_read(sl=sl, sa=True)
sa.append(read_fifo(3)) sa.append(ifc._read_fifo(3))
n -= 1 n -= 1
for s in sa: for s in sa:
if (s[0] & 0xfffc) != 0x5714: if (s[0] & 0xfffc) != 0x5714:

View file

@ -113,16 +113,16 @@ static int filter(struct command *cmd, const struct command_par *par)
unsigned int slot = 0; unsigned int slot = 0;
error_msg_t e = parse_flag(cmd, kws, &kw, 0); error_msg_t e = parse_flag(cmd, kws, &kw, 0);
if (!e) if (!e)
e = parse_expression_square(cmd, &ch, 2); e = parse_expression_square(cmd, &ch, optional_brackets|optional_close);
if (!e) if (!e)
e = parse_expression_square(cmd, &slot, 2); e = parse_expression_square(cmd, &slot, optional_brackets|optional_open);
if (!e && (ch>=2 || slot>=16)) if (!e && (ch>=2 || slot>=16))
e = &parser_value_error; e = &parser_value_error;
if (e) if (e)
return parser_error_message(cmd, e); return parser_error_message(cmd, e);
unsigned int what = kw->val | (ch<<7) | (slot<<3); unsigned int what = kw->val | (ch<<7) | (slot<<3);
char name[16]; char name[16];
snprintf(name, sizeof(name), "%s[%d][%d]", kw->name, ch, slot); snprintf(name, sizeof(name), "%s[%d,%d]", kw->name, ch, slot);
return altera_set_register(cmd, par, 0x0, 0, what, name); return altera_set_register(cmd, par, 0x0, 0, what, name);
} }

View file

@ -1,5 +1,11 @@
@s/if !ssp_dma: s/exit @s/if !ssp_dma: s/exit
@clock/short @clock/short
@s/if sec==0: nm/count/clear/float; s/exit @v S = sec % 10
@s/if sec==2: pressure/inject; s/exit @s/if S == 0: al/cmd/inj/res 0x30
@s/if sec==4: pressure/inject/p2; s/exit @s/if S == 0: nm/cou/re/cl/fl; s/exit
@s/if S == 1: chaos/cmd 'W'; chaos/hk; s/exit
@s/if S == 2: var hk_c=1; chaos/adc 0x8ff; s/exit
@s/if S == 3 and hk_mes: var hk_c=hk_mes-1; s/exit
@s/if S == 4: chaos/cmd 'H' H; s/exit
@s/if S == 6: pressure/inject/p1; s/exit
@s/if S == 7: pressure/inject/p2; s/exit

View file

@ -1,3 +1,6 @@
@clock/short @clock/short
@s/if sec==5: v hk_c=1; s/exit @s/if sec & 1 and I: al/cmd/inj I; s/exit
@s/if sec==0: nm/cou/re/cl/fl; s/exit
@s/if sec==2 and H: al/cmd/inj H
@s/if sec==4: v hk_c=1; s/exit
@s/if sec==6 and hk_mes>1: v hk_c=hk_mes-1; s/exit @s/if sec==6 and hk_mes>1: v hk_c=hk_mes-1; s/exit

Binary file not shown.

View file

@ -0,0 +1,2 @@
v H = 0x00f0e08b
v I = 0

197
i2c.c Normal file
View file

@ -0,0 +1,197 @@
#include "i2c.h"
#include "altera.h"
#include "expression.h"
// Any non [bracketed] parameters may spill over to higher orde bits
// Not all combinations of /flags are applicable.
// /alt/cmd flags must follow the arguments. The argument then needs to be in []
unsigned int i2c_register = 0x8032;
unsigned int i2c_address, i2c_size;
const struct
keywords i2c_variable_names[] = {
{"i2c_register", {.par=&i2c_register}},
{"i2c_address", {.par=&i2c_address}},
{"i2c_size", {.par=&i2c_size}},
KW_END
};
static const
struct keywords i2c_write_kw[] = {
{"read", {.val= 0x0001 }}, // /restart/read/mag
{"autoincr", {.val= 0x0080 }}, // /reg/auto
{"ifactive", {.val= 0x0400 }},
{"ifack", {.val= 0x0800 }},
{"resume", {.val= 0x1000 }},
{"save", {.val= 0x1000 }},
{"send", {.val= 0x4000 }},
{"magnetometer", {.val= 0x003c }},
{"accelerometer", {.val= 0x0032 }},
{"discard", {.val= 0x2000 }},
{"last", {.val= 0x0200 }},
{"continue", {.val= 0 }}, // /read/cont (clear /last)
KW_END
};
// i2c_write() writes an action word into the I²C batch memory
//
// /start a send start and address (8-bit)
// /start/read a send start with read bit and address (8-bit)
// /restart/read a send restart, i.e., require the previous start to be acked
// /stop send stop
// /unstuck send an unstuck sequence
// /write d write anything, send a data byte
// /read n read n+1 data bytes and flag the last one
// /read/cont n read n+1 data bytes, do not flag the last one
// /reg r send a register addr, /save the addr as data
// /reg/auto r send a register addr with MSB set
//
// Flags:
//
// /read set LSB of the data, use with /restart
// /auto set the MSB of the data byte, use with /reg
// /ifact require the I²C unit to be active (acked /start)
// /ifack require the last byte being acked
// /resume continue after being blocked by /ifa…
// /save save the data byte, to be sent with the next odd read. Use with /reg
// /send send this command frame to the fifo, use with anything
// /discard do not send the data to the fifo, use with /read
// /last do not use, /read == /write/last, /stop == /start/last
// /cont use as /read/cont, /read/cont == /write, do not flag the last byte for reads
int i2c_write(struct command *cmd, const struct command_par *par)
{
unsigned int c = (unsigned int)(par->par);
error_msg_t e = parse_flags(cmd, i2c_write_kw, &c);
unsigned int cc = (c <<= 16) | i2c_register | 0xc001;
if (!e && (cc & 0x03000000) != 0x03000000)
// /stop and /unstuck do not use an agrument
e = parse_expression_square(cmd, &c, optional_brackets);
if (e)
return parser_error_message(cmd, e);
cc |= c<<16;
i2c_size ++;
return altera_set_register(cmd, par, 0, alt_cmd_inj, cc, "i2c");
}
// i2c_addr() commands the I²C engine.
// Both the data and addr commands are supported.
// It is meant to set the batch address pointer and run the batch
//
// /data read status, reset, A={0,0}
// /addr read status
// /addr [a] write A={0,a}
// /addr a write A={a}
// /addr [a] n write A={n,a}
// /data d write D={d}
// /data [l] h write D={h,l}
// /data [l] write D={0,l}
// /run write A={i2c_size, i2c_address}
// /run [a] write A={i2c_size, a}
// /run n write A={a, i2c_address}
int i2c_addr(struct command *cmd, const struct command_par *par)
{
unsigned int what = (unsigned int)(par->par);
unsigned int a = -1;
unsigned int n = 0;
unsigned int how = 0;
if (what & 2) {
how = alt_cmd_inj;
a = i2c_address;
n = i2c_size;
}
error_msg_t e = parse_expression_square(cmd, &a, optional_empty | optional_close);
if (e)
return parser_error_message(cmd, e);
e = parse_expression_square(cmd, &n, optional_brackets | optional_open);
n <<= 16;
if (a < 0x0100)
n = (n<<8) | (a<<16) | 0x4000;
n |= i2c_register | what & 1;
if (!e)
n |= 0x4000;
switch (n & 0x4001) {
case 0x0001:
a = 0;
case 0x4000:
i2c_address = a;
i2c_size = 0;
break;
case 0x4001:
i2c_size += 1;
}
return altera_set_register(cmd, par, 0, how, n, "i2c");
}
static const
struct keywords i2c_wait_kw[] = {
{"buffer", {.val= 0x1000 }},
{"release", {.val= 0x2000 }},
{"loop", {.val= 0x1000 }},
KW_END
};
// i2c_header() write a packet header or wait item to the I²C batch memory
//
// /head [magic] size start a packet, total size is size+1
// /wait ms wait for ms milliseconds
//
// Flags:
//
// /head/buffer Write the packet data into the buffer
// …/release Release the buffered data to the packetfifo (both)
// /wait/loop Restart the current batch after the wait.
//
// Typical batch:
//
// /addr a set batch start addr, saved in i2c_address
// /wait/release 2 release the dat from the buffer from the previous run
// /head/buffer [m] s Start a new packet in the buffer
// /start … generate the packet data
// … …
// /stop …
// /wait/loop t optional: restart with a certain cadence
//
// /run i2c_size-1 run the batch without loop
// /run run the batch with loop
int i2c_header(struct command *cmd, const struct command_par *par)
{
unsigned int c = (unsigned int)(par->par);
error_msg_t e = parse_flags(cmd, i2c_wait_kw, &c);
unsigned int cc = (c <<= 16) | i2c_register | 0xc001;
if (!e) {
c = 0;
e = parse_expression_square(cmd, &c, optional_empty | optional_close);
cc |= c<<24;
}
if (!e) {
c = 0;
e = parse_expression_square(cmd, &c, optional_any | optional_open);
cc |= c<<16;
}
if (e)
return parser_error_message(cmd, e);
i2c_size ++;
return altera_set_register(cmd, par, 0, alt_cmd_inj, cc, "i2c");
}
static const struct keywords i2c_commands[] = {
CMD_KW("addr", i2c_addr, 255, (void*)(0)),
CMD_KW("run", i2c_addr, 255, (void*)(2)),
CMD_KW("data", i2c_addr, 255, (void*)(1)),
CMD_KW("wait", i2c_header, 255, (void*)(0xc000)),
CMD_KW("header", i2c_header, 255, (void*)(0x8000)),
CMD_KW("start", i2c_write, 255, (void*)(0x0100)),
CMD_KW("restart", i2c_write, 255, (void*)(0x0500)),
CMD_KW("stop", i2c_write, 255, (void*)(0x0300)),
CMD_KW("unstuck", i2c_write, 255, (void*)(0x2300)),
CMD_KW("write", i2c_write, 255, (void*)(0x0000)), // omnipotent
CMD_KW("register", i2c_write, 255, (void*)(0x2000)), // implies /save
CMD_KW("read", i2c_write, 255, (void*)(0x0200)), // implies /last
{"", {.par=&parser_unknown_command}}
};
COMMAND(i2c_command, parse_sub_command, 909, i2c_commands);

3
i2c.h Normal file
View file

@ -0,0 +1,3 @@
#include "parser.h"
extern const struct command_par i2c_command;
extern const struct keywords i2c_variable_names[];

View file

@ -40,6 +40,9 @@ BEGIN {
T_R25 = 10e3 T_R25 = 10e3
nEa = 60 nEa = 60
Time1 = 1.7e9
Time2 = 2e9
if (UNIT) @UNIT() if (UNIT) @UNIT()
} }
@ -193,6 +196,23 @@ function isCHAOS() {
return 1; return 1;
} }
function isCHAOS_SP() {
is2D(D1H,D2H)
BGO = A+B
if (BGO > 50) return 0
SSDA = 0
if (isPHA(A1H) > 1) SSDA = A
if (isPHA(A2H) > 1 && A > SSDA) SSDA = A
if (SSDA > 12) return 0
SSDC = 0
if (isPHA(C1H) > 1) SSDC = A
if (isPHA(C2H) > 1 && A > SSDC) SSDC = A
if (SSDC > 12) return 0
CHER = 0
if (isPHA(CHK) > 1) CHER = A
return 1;
}
function CHAOSHK() { function CHAOSHK() {
if (!/^HC/ || !/ 0x00ff5454 /) return 0 if (!/^HC/ || !/ 0x00ff5454 /) return 0
if ($2<Time) return 0 if ($2<Time) return 0
@ -831,8 +851,8 @@ END {
function isTime() { function isTime() {
if (!/^H /) return 0 if (!/^H /) return 0
Time = $2 Time = $2
if (Time > 2000000000) return 0 if (Time > Time2) return 0
if (Time < 1700000000) return 0 if (Time < Time1) return 0
TS = 0 TS = 0
for (s in TIMESHIFT) { for (s in TIMESHIFT) {
if (Time>=TIMESHIFT[s][1] && Time<=TIMESHIFT[s][2]) { if (Time>=TIMESHIFT[s][1] && Time<=TIMESHIFT[s][2]) {

View file

@ -39,6 +39,8 @@
#include "spw.h" #include "spw.h"
#include "led.h" #include "led.h"
#include "chaos.h" #include "chaos.h"
#include "dorn.h"
#include "i2c.h"
// collect command submissions from various sources // collect command submissions from various sources
@ -99,7 +101,7 @@ static int echo_command(struct command *cmd, const struct command_par *par)
what = (unsigned int)par->par; what = (unsigned int)par->par;
unsigned int val = what & 0xff; unsigned int val = what & 0xff;
if (!e) if (!e)
e = parse_expression_square(cmd, &val, 1); e = parse_expression_square(cmd, &val, optional_expression);
if (e) if (e)
return parser_error_message(cmd, e); return parser_error_message(cmd, e);
if (val < (what&0xff)) if (val < (what&0xff))
@ -475,15 +477,9 @@ int main_loop_last_code;
struct command_par plugin_commandtable = {parse_plugin_command, 0, 0}; struct command_par plugin_commandtable = {parse_plugin_command, 0, 0};
static COMMAND(echo_par, echo_command, 199, 0);
static COMMAND(message_par, echo_message, 100, 0);
static COMMAND(sleep_par, sleep_command, 197, 0);
static COMMAND(clock_par, clock_command, 180, 0);
static COMMAND(uart_par, uart_command, 196, 0);
static const struct keywords main_command_table[] = { static const struct keywords main_command_table[] = {
{"echo", {.par=&echo_par}}, CMD_KW("echo", echo_command, 199, 0),
{"message", {.par=&message_par}}, CMD_KW("message", echo_message, 100, 0),
{"file", {.par=&script_command}}, {"file", {.par=&script_command}},
{"script", {.par=&script_command}}, {"script", {.par=&script_command}},
{"flash", {.par=&flash_command}}, {"flash", {.par=&flash_command}},
@ -493,8 +489,8 @@ static const struct keywords main_command_table[] = {
{"sdcard", {.par=&sdcard_command}}, {"sdcard", {.par=&sdcard_command}},
{"ethernet",{.par=&eth_command}}, {"ethernet",{.par=&eth_command}},
{"variable",{.par=&variable_commands}}, {"variable",{.par=&variable_commands}},
{"sleep", {.par=&sleep_par}}, CMD_KW("sleep", sleep_command, 197, 0),
{"clock", {.par=&clock_par}}, CMD_KW("clock", clock_command, 180, 0),
{"spi", {.par=&plugin_command}}, {"spi", {.par=&plugin_command}},
{"flyrena", {.par=&flyrena_command}}, {"flyrena", {.par=&flyrena_command}},
{"sirena", {.par=&sirena_command}}, {"sirena", {.par=&sirena_command}},
@ -507,9 +503,11 @@ static const struct keywords main_command_table[] = {
{"nm64", {.par=&nm64_command}}, {"nm64", {.par=&nm64_command}},
{"spw", {.par=&spw_command}}, {"spw", {.par=&spw_command}},
{"led", {.par=&led_command}}, {"led", {.par=&led_command}},
{"uart", {.par=&uart_par}}, CMD_KW("uart", uart_command, 196, 0),
{"usb", {.par=&usb_command}}, {"usb", {.par=&usb_command}},
{"chaos", {.par=&chaos_command}}, {"chaos", {.par=&chaos_command}},
{"dorn", {.par=&dorn_command}},
{"i2c", {.par=&i2c_command}},
CMD_KW("arm", arm_command, 195, 0), CMD_KW("arm", arm_command, 195, 0),
{"", {.par=&plugin_commandtable}}, {"", {.par=&plugin_commandtable}},
@ -744,7 +742,7 @@ __attribute__((noreturn))
void main_loop(void) void main_loop(void)
{ {
uart_init(); uart_init();
message(0, "\n%s ARM rev %d, prod ffff:%04x, sn %d\n", message(0, "\n%s ARM rev %08x, prod ffff:%04x, sn %d\n",
irena_name, Revision, 0xee00+ProductId, SerialNumber); irena_name, Revision, 0xee00+ProductId, SerialNumber);
stack_report(); stack_report();
uart_enable_commands(); uart_enable_commands();
@ -906,6 +904,7 @@ const struct keywords *variable_names[] = {
nm64_variable_names, nm64_variable_names,
spw_variable_names, spw_variable_names,
chaos_variable_names, chaos_variable_names,
i2c_variable_names,
0 0
}; };

View file

@ -4,11 +4,12 @@
from arena import * from arena import *
import math import math
from time import sleep from time import sleep
import arena, scangen import dorn, arena, scangen
from dorn import * from dorn import *
ifc,_oo = armlib.init_irena(scope = globals(), name = "NARENA", prod = 0xee02) ifc,_oo = armlib.init_irena(scope = globals(), name = "NARENA", prod = 0xee02)
arena._connect(ifc) arena._connect(ifc)
dorn._connect(ifc)
ifc._stream_fifos="hk1/f1/f2/f3" ifc._stream_fifos="hk1/f1/f2/f3"
if ifc.is_a("USB"): if ifc.is_a("USB"):
@ -25,21 +26,8 @@ from lasc import SCstart, SCread
def SCplot(sc, CDIV=6, **kk): def SCplot(sc, CDIV=6, **kk):
osc.LASCplot(None, sc, CDIV=CDIV, **kk) osc.LASCplot(None, sc, CDIV=CDIV, **kk)
AHEPAM_CONFIG.update({ dorn.CONFIG.dorn_addr = 0x800
"dorn_addr": 0x800, dorn.CONFIG.n_channels = 12
"n_channels": 12
})
l2_set6 = (
(0, -1203, 0),
(1, -1203, 0),
(2, -1203, 0),
(3, -1186, 0),
(4, -39, 2000),
(5, 1709, 970),
(6, 2000, -1082),
(7, 1125, -1888),
)
def narena_hk(sl, what="data", data=None, ND=4, NV=8, Vref=3.3): def narena_hk(sl, what="data", data=None, ND=4, NV=8, Vref=3.3):
"""what="data", "raw", "cooked", "print" (default)""" """what="data", "raw", "cooked", "print" (default)"""

2
nm64.c
View file

@ -783,7 +783,7 @@ static int hv_dac(struct command *cmd, const struct command_par *par)
error_msg_t e = parse_flags(cmd, kw, &step); error_msg_t e = parse_flags(cmd, kw, &step);
unsigned int idx, uv, uvs; unsigned int idx, uv, uvs;
if (!e) if (!e)
e = parse_expression_square(cmd, &idx, 2); e = parse_expression_square(cmd, &idx, optional_brackets);
if (!e && idx>=4) if (!e && idx>=4)
e = &parser_value_error; e = &parser_value_error;
if (!e) { if (!e) {

View file

@ -10,14 +10,13 @@ ls $(date +'nm64/kiel/nm64_kiel_%Y-%m-%dT*Z.dat' -d -1day) $(date +'nm64/kiel/nm
# temporarily disable cron emails # temporarily disable cron emails
##exec 2>&1 ##exec 2>&1
rsync -av --exclude '/*/' etbern4.etph:/home/etbern4/nm64/solo/eda/arm/nm64/data/ /data/falbala/nm64/data/jfj/igy/ rsync -av --exclude '/*/' -e 'ssh -Jnm64@cosray.unibe.ch' igy.hfsjg.unibe.ch:/home/etbern4/nm64/solo/eda/arm/nm64/data/ /data/falbala/nm64/data/jfj/igy/
ls $(date +'nm64/jfj/igy/JFJ_IGY*_%Y-%m-%dT*Z.dat' -d -1day) $(date +'nm64/jfj/igy/JFJ_IGY*_%Y-%m-%dT*Z.dat') | sed 's,.dat$,.nm_raw,' | xargs make 2>&1 ls $(date +'nm64/jfj/igy/JFJ_IGY*_%Y-%m-%dT*Z.dat' -d -1day) $(date +'nm64/jfj/igy/JFJ_IGY*_%Y-%m-%dT*Z.dat') | sed 's,.dat$,.nm_raw,' | xargs make 2>&1
#rsync -av --exclude '/*/' -e 'ssh -Jetbern4.etph' etbern2:/home/etbern2/nm64/solo/eda/arm/nm64/data/ /data/falbala/nm64/data/jfj/nm64/ rsync -av --exclude '/*/' -e 'ssh -Jnm64@cosray.unibe.ch' nm64.hfsjg.unibe.ch:/home/etbern2/nm64/solo/eda/arm/nm64/data/ /data/falbala/nm64/data/jfj/nm64/
rsync -av --exclude '/*/' etbern2.etph:/home/etbern2/nm64/solo/eda/arm/nm64/data/ /data/falbala/nm64/data/jfj/nm64/
ls $(date +'nm64/jfj/nm64/JFJ_NM64_%Y-%m-%dT*Z.dat' -d -1day) $(date +'nm64/jfj/nm64/JFJ_NM64_%Y-%m-%dT*Z.dat') | sed 's,.dat$,.nm_raw,' | xargs make 2>&1 ls $(date +'nm64/jfj/nm64/JFJ_NM64_%Y-%m-%dT*Z.dat' -d -1day) $(date +'nm64/jfj/nm64/JFJ_NM64_%Y-%m-%dT*Z.dat') | sed 's,.dat$,.nm_raw,' | xargs make 2>&1
rsync -av --exclude '/*/' etbern3.etph:/home/etbern3/nm64/solo/eda/arm/nm64/data/ /data/falbala/nm64/data/bern/ rsync -av --exclude '/*/' -e 'ssh -Jnm64@cosray.unibe.ch' kspc16.unibe.ch:/home/etbern3/nm64/solo/eda/arm/nm64/data/ /data/falbala/nm64/data/bern/
ls $(date +'nm64/bern/nm64_rolf_%Y-%m-%dT*Z.dat' -d -1day) $(date +'nm64/bern/nm64_rolf_%Y-%m-%dT*Z.dat') | sed 's,.dat$,.nm_raw,' | xargs make 2>&1 ls $(date +'nm64/bern/nm64_rolf_%Y-%m-%dT*Z.dat' -d -1day) $(date +'nm64/bern/nm64_rolf_%Y-%m-%dT*Z.dat') | sed 's,.dat$,.nm_raw,' | xargs make 2>&1
ls $(date --utc +'nm64/kiel/nm64_kiel_%Y-%m-%dT%H:*Z.nm_raw') | xargs -i bash -c '[ -s "{}" ] || echo empty "{}" >&2' ls $(date --utc +'nm64/kiel/nm64_kiel_%Y-%m-%dT%H:*Z.nm_raw') | xargs -i bash -c '[ -s "{}" ] || echo empty "{}" >&2'

107
nmahepam.py Executable file
View file

@ -0,0 +1,107 @@
#! /usr/bin/ipython3 --profile=nmahepam
# encoding: UTF-8
import armlib, dorn, sys, math, time
def HK():
Vcc = hk2mvolt("adc_Vpcsa")*0.002
Vss = hk2mvolt("adc_Vmcsa")*(-0.002)
Icc = hk2mvolt("adc_Ipcsa")*0.1
Iss = hk2mvolt("adc_Imcsa")*(-0.1)
Vprim = hk2mvolt("adc_Vprim")*(0.011)
Vbias = hk2mvolt("adc_Vbias")*(-0.05)
Ibias = hk2mvolt("adc_Ibias")*0.0955
r = (Vcc, Vss, Icc, Iss, Vprim, Vbias, Ibias)
print("Vcc:%4.2fV, Vss:%4.2fV, Icc:%6.1fmA, Iss:%6.1fmA, Vprim:%4.1fV, Vbias:%.1fV Ibias:%.1fnA" % r)
return r
def findnmahepam():
findxrena(prod=(0xee0c,))
if connected_p():
set_clock()
messages()
HK()
#TO DO: Adjust
def hk(sl, what="print", data=None):
if not data:
ecmd("alt/stream/off")
menable()
dorn.fifo_enable(en=True, sl=sl, hk=True)
dorn.fifo_reset(sl=sl, hk=True)
dorn.strobe(sl=sl, hk=True)
time.sleep(0.1)
dorn.fifo_read(sl=sl, hk=True)
data=read_fifo()
if data[0] != 0x5710 + sl:
raise ValueError("Read HK packet error", data)
if what=="data":
return data
ND = dorn.CONFIG.n_adc()
NV = ND
data = [d & 0xfff for d in data]
data = [data[ND*i+1:ND*i+1+NV] for i in range(8)]
if what=="raw":
return data
Vref = dorn.CONFIG.Vref(sl)/4096
#NMAHEPAM:data[7][0] *= 2*Vref/4096 # Vcore
data[4][0] = degC(data[4][0], 0) # T_BGO,EXT
data[4][1] = degC(data[4][1], 0) # T_BGO,NTC
data[4][2] *= -Vref/0.047 # V_bias
data[4][3] = degC(data[4][3], 0) # T_BGO,REF
data[4][4] *= Vref * 10470/470 * 51/1051 * 100 # Ibias
data[4][5] *= Vref * 10470/470 * 51/1051 * 100 # Ibias
data[4][7] *= Vref * 2 # VCC
data[4][6] *= Vref * 2.5 # VSS
data[4][6] -= 1.5*data[4][7] # VSS
data[3][0] *= Vref * 10470/470 * 51/1051 * 100 # Ibias
data[3][1] *= Vref * 2 # Vff
data[3][3] *= Vref * 2 # Vpp (V+6V)?
data[3][2] *= Vref * 2.5 # Vnn
data[3][2] -= 1.5*data[3][3] # Vnn
data[3][4] *= Vref * 2 # Vdig (Vadc)
data[3][5] = degC(data[3][5], 0) # NTC ?
data[3][6] *= Vref * 2 # VCC
data[3][7] *= Vref * 2.5 # VSS
data[3][7] -= 1.5*data[3][6] # VSS
if what=="cooked":
return data
r = f"""# nmahepam HK:
0. {data[0]}
1. {data[1]}
2. {data[2]}
3. ADC board
T = {data[3][5]:6.2f} °C
Ibias = {data[3][0]:6.3f} V
Vff = {data[3][1]:6.3f} V , Vnn = {data[3][2]:6.3f} V, Vpp = {data[3][3]:6.3f} V, Vdig = {data[3][4]:6.3f} V
Vcc = {data[3][6]:6.3f} V, Vss = {data[3][7]:6.3f} V
4. PA board
Tbgo = {data[4][0]:6.2f} °C, {data[4][1]:6.2f} °C, {data[4][3]:6.2f} °C
Vbias = {data[4][2]:6.3f} V, Ibias = {data[4][4]:6.1f} nA, {data[4][5]:6.1f} nA
Vcc = {data[4][7]:6.3f} V, Vss = {data[4][6]:6.3f} V
5. {data[5]}
6. {data[6]}
7. {data[7]}
"""
if what=="print":
sys.stderr.write(r)
return r
def aenable(sl=1, hk=True, ev=True, **aa):
cmd("s/cron 'CRON.RC'")
fifo_enable(sl=sl, hk=hk, ev=ev, **aa)
enable()
if __name__=="__main__":
ifc,_oo = armlib.init_irena(scope = globals(), name = "AHEPAM", prod = (0xee0c,))
ifc._stream_fifos = 'hk1/f1/f2/f3'
if ifc.is_a("USB"):
findnmahepam()
from dorn import *
dorn._connect(ifc)

View file

@ -371,26 +371,52 @@ int parser_dump(struct command *cmd, const struct command_par *par)
ERRORMESSAGE(err_noblock, 951, "no usb data block"); ERRORMESSAGE(err_noblock, 951, "no usb data block");
// optional = 0: '[' «expr» ']'
// optional = 1: [ '[' «expr» ']' ]
// optional = 2: [ '[' ] «expr» [ ']' ]
// optional = 3: [ [ '[' ] «expr» [ ']' ] ]
error_msg_t parse_expression_square(struct command *cmd, unsigned int *r, int optional) error_msg_t parse_expression_square(struct command *cmd, unsigned int *r, int optional)
{ {
error_msg_t e = expect_char(cmd, '['); static int isopen;
if (e && optional==1) error_msg_t e = 0;
return 0; if (!(optional & optional_open && isopen))
if (e && optional==0) e = expect_char(cmd, '[');
return e; isopen = 0;
if (e && !(optional_open & optional_brackets))
if (optional_open & optional_expression)
return 0;
else
return e;
if (!e && optional & optional_in_brackets)
if (parse_char(cmd, ']'))
return 0;
else if (optional & optional_close && parse_char(cmd, ',')) {
isopen = 1;
return 0;
}
error_msg_t ee = parse_expression(cmd, r); error_msg_t ee = parse_expression(cmd, r);
if (!e && !ee) if (!e && !ee) {
ee = expect_char(cmd, ']'); ee = expect_char(cmd, ']');
if (!e || optional==2) if (ee && optional & optional_close) {
isopen = 1;
ee = expect_char(cmd, ',');
}
}
if (!e || !(optional & optional_expression))
return ee; return ee;
return 0; return 0;
} }
error_msg_t parse_index(struct command *cmd, unsigned int *r, unsigned int m, unsigned int b, int optional)
{
unsigned int a;
error_msg_t e = parse_expression_square(cmd, &a, optional);
if (!e && a > m)
e = &parser_value_error;
if (e)
return e;
a <<= b;
a |= *r & ~(m << b);
*r = a;
return 0;
}
error_msg_t error_printf(unsigned int code, const char *m, ...) error_msg_t error_printf(unsigned int code, const char *m, ...)
{ {
static char mes[64]; static char mes[64];

View file

@ -83,6 +83,18 @@ extern const struct command_par parser_keyword_error;
#define KW_END {"", {0}} #define KW_END {"", {0}}
error_msg_t parse_expression_square(struct command *cmd, unsigned int *r, int optional); error_msg_t parse_expression_square(struct command *cmd, unsigned int *r, int optional);
error_msg_t parse_index(struct command *cmd, unsigned int *r, unsigned int m, unsigned int b, int optional);
enum {
optional_expression = 1, // The expression is optional
optional_brackets = 2, // The brackets around the expression are optional
optional_in_brackets = 4, // Empty brackets are permitted
optional_open = 8, // Accept a previously opened bracket
optional_close = 16, // May leave the bracket open, with a ','
optional_number = 3, // optional expression, optionally bracketed.
optional_empty = 5, // Optional expression, with brackets, maybe empty
optional_any = 7, // Everything optional
};
static inline void cmd_push(struct command *cmd, struct command *save) static inline void cmd_push(struct command *cmd, struct command *save)
{ {