Minecoprocessors

Minecoprocessors

183k Downloads

Submission for example programs: Falling Edge Detector

Zexks opened this issue ยท 7 comments

commented

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.

commented

@frodare Hi, I just stumbled over this, should the GPIO read 0xf or 0x1? If ladder I could quickly make the change. Cheers.

commented

@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.

commented
//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.

commented

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 Carry and Zero 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,-

commented

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 Carry and Zero instead. CMP a, b: The carry bit is set if a<b, zero bit if a==b, none of both if a>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.

commented

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?

commented

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 ANDs 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.