Submission for example programs: Falling Edge Detector
Zexks opened this issue ยท 7 comments
mov ports, 0010b
start:
cmp pb, 0
jz start
wait:
cmp pb, 0
jnz wait
mov pf, 1b
mov c, 5
loop:
dec c
jnz loop
mov pf, 0
jmp start
Used this for several machines that require crafting mods to do a single craft at a time. AE2 has a setting called blocking mode but other mods require redstone signals between crafts.
Still seems to have issues with recognizing '1' in the cmp command. tried with 0xff but couldn't get that to work either. Had to go off 0 checks.
@frodare Hi, I just stumbled over this, should the GPIO read 0xf or 0x1? If ladder I could quickly make the change. Cheers.
@stfwi It has been long enough since I built this mod that I am not sure. I think I wanted to represent 1 as 0x1, but at some point it was outputting 0xf.
//code
Used this for several machines that require crafting mods to do a single craft at a time. AE2 has a setting called blocking mode but other mods require redstone signals between crafts.
Still seems to have issues with recognizing '1' in the cmp command. tried with 0xff but couldn't get that to work either. Had to go off 0 checks.
@Zexks
It seems that the ports in Digital mode read out as either 0x00 or 0xFF. In ADC mode, they read from 0x0 to 0xF. You have a few options to read "if port is High" (if any redstone signal at back):
Have pb
in ADC mode, and use cmp pb, 0x01
with jge
to jump if high
OR
Have pb
in digital mode, and use cmp pb, 0xFF
with jz
/je
to jump if high
OR
Have pb
in digital mode, and use cmp pb, -1
with jz/je
to jump if high
Any of these should work as a "jump if port is high" snippet
Test code to show what a port reads in as:
mov ports, 0010b
;mov adc, 0010b
mov a, pb
sp:
jmp sp
Comment/uncomment the second line to switch between digital/analog modes respectively.
Register a
will have in it whatever was in the back port on putting in the book. You can mouse over a
in the GUI to see it's value in both hex and decimal.
Technically, in digital mode, a port being high reads as decimal -1
because 2's complement 0xFF
is -1
decimal, which is why cmp pb, 1
wasn't working.
Just read more into the issue, saw this:
tried with 0xff but couldn't get that to work either.
I tried this program:
mov ports, 0010b
m:cmp pb, 0xFF
jz yes
jmp m
yes:mov b, 0xBB
jmp m
Once pb
goes high, b
gets set to 0xBB
as expected, therefore the comparison with 0xFF
works.
Tested with mod version 1.0.5-b1, on Forge 36.1.0, Minecraft 1.16.5.
Hey guys, independent of the current PR addressing the 0x1/0xff digital values, I would recommend to use the AND
instruction for bitwise checks, or compare zero, like
MOV a, pb
AND a, 0xff ; or CMP a, 0x00
JNZ powered
unpowered:
; do stuff
JMP cond_done
powered:
; do stuff
cond_done:
...
That way it does not matter if the port is in digital or analog mode.
(A compare instruction is like a subtraction, except that it does not change the register, but sets or clears C
arry and Z
ero instead. CMP a, b
: The carry bit is set if a<b
, zero bit if a==b
, none of both if a>b
). Maybe a bit-test instruction could be interesting for getting something like the bitwise comparison shown above, but without the need to MOV a, pb
first (at least not if we respect the input read-only). IIRC BIT
should be that on small RISC CPUs.
Keep it up guys, cheers,-
Hey guys, independent of the current PR addressing the 0x1/0xff digital values, I would recommend to use the
AND
instruction for bitwise checks, or compare zero, likeMOV a, pb AND a, 0xff ; or CMP a, 0x00 JNZ powered unpowered: ; do stuff JMP cond_done powered: ; do stuff cond_done: ...That way it does not matter if the port is in digital or analog mode.
(A compare instruction is like a subtraction, except that it does not change the register, but sets or clears
C
arry andZ
ero instead.CMP a, b
: The carry bit is set ifa<b
, zero bit ifa==b
, none of both ifa>b
).
Yeah, I've seen the Wiki page for how CMP a,b
is just "subtract but only change the carry and zero flags". It's probably good to have it noted here though too for anyone that's searching that that's how CMP
works, and that's why CMP
isn't doing what they'd expect for certain numbers.
This snippet does work, and it's good for preserving the 0x0-0xF value of that port if it's being used in the do stuff
blocks. That said, it clobbers a register.
In my experience, CMP port, constant
, when working with the ports in digital mode, is usually better since it doesn't clobber a register to directly CMP
a port to a constant. It's one instruction less, three less if you want to preserve and restore the clobbered register using the stack, but granted directly accessing the register doesn't allow the use of boolean operators like AND or such without violating the read-only nature of the port registers in input mode.
You could shorten down that snipped to this, if you're sure that pb
is in Digital mode:
CMP pb, 0x00
JNZ powered
unpowered:
; do stuff
JMP cond_done
powered:
; do stuff
cond_done:
...
There's also a case to be made regarding input to use the (as far as I can tell) unused upper nybble of the ADC register to have a "legacy" mode for Digital, where the registers read out 0xFF
or 0x00
as they used to be with the pre-PR digital. It'd be nice for things like XOR a, pb
, but it would prevent any other features or use of that nybble, such as setting indirection registers or just a free extra nybble of workspace.
Hi, aye, totally, compare-zero is the best thing for single value query. The unused port bit usage is also a good aspect. The PR is related to the descriptions in the wiki, hence the change to 0x1.
Similar to the fewer cycles needed, I am wondering if the bit-testing instruction mentioned could be interesting for the new (if accepted) IDR register. To latch and check ports in one go, e.g. AND
would be needed without, I mean ...
loop:
WFE
MOV a, idr ; latch all I/O port states in lower nibble
AND a, match
JNZ case_b
case_a:
; do a
JMP done
case_b:
; do b
done:
...
Bit testing replaces that with a boolean result in Z
:
loop:
WFE
BIT idr, match
JNZ case_b
case_a:
; do a
JMP done
case_b:
; do b
done:
...
Similar to the compare-zero - without clobbering a register.
Would that be a thing worth implementing?
I am wondering if the bit-testing instruction mentioned could be interesting for the new (if accepted) IDR register.
Assuming this is the mentioned proposal:
Maybe a bit-test instruction could be interesting for getting something like the bitwise comparison shown above, but without the need to MOV a, pb first
I assume that BIT value, match
AND
s each bit of value
with each bit of match
, and sets the Z
flag accordingly, with the resulting functionality being:
jnz
is "jump if any bits of value
are also set in match
", and
jz
is "jump if no bits of value
are also set in match
",
like a CMP
version of AND
?
If this is what it'd do, I see how it's not possible to do that with CMP
since subtraction can't "ignore" bits like AND
can, and I see the benefits of this especially with having separate inputs mapped to bits of a register. It can't test if value
matches mask
directly, but that's already handled by CMP
, so it definitely sounds like a QOL improvement and a useful new feature.
In the second quote, I assume the comparison referred to here, AND a, 0xFF
is "test if any bit of a
is set", and your proposal is to be able to replace that with BIT pb, 0xFF
? It'd for sure be nice to have something that concise to use to test specific bits, especially with IDR
adding a need to do that kind of bit testing.