Shenzhen I/O: Diagnostic Pulse Generator

The third task we get is playing solitaire, but ignoring that the third programming puzzle we get is that we need to test some manufacturing equipment. We can do that by building a diagnostic pulse generator that sends a pulsing signal to the output whenever we hold a button.

The board looks like this where the button is a simple input. When it goes high we should generate a pulse to the pulse output with a certain characteristic.

The verification signals look like

So basically we need to send a pulses when ever we press the button. I have no less than three different solutions.

The straight forward solution

The first solution is the solution you should be able to make based on the knowledge you have from the game and the manual by now. It uses conditional expressions for the first time in the game.

Let us first see how we can generate a pulsing signal. After that we will deal with when to make it. There is a small trick to this. Which requires us to use an arithmetic instruction

That is the not operation – which will flip the acc from 0 to 100 or vice versa.

This is a pretty useful in this case, as we can just trigger not, and then move acc to p1 then we have a pulsing signal!

For the condition around when to generate the pulse we need to use conditionals we can use the following

tgt R/I R/I – this will test if the first operand is greater than the second operand. If that is the case any instruction marked with a + afterwards will be executed. If that is false any operation marked with a – will be triggered.

Which leads us to the following code

```  tgt p0 0
+ not
- mov 0 acc
mov acc p1
slp 1
```

which in the game looks like

We test to see if the button is pressed. If that is the case we start sending the pulsing signal. If the button is unpressed we reset the acc to zero. Then we move the acc to p1 and sleep.

Second diagnostic pulse generator solution

When we analyse the output we will see that we cannot unpress the button and then press it again to reset the signal. The game is simply not made that way.

This means that we can just generate a pulse that is high and then low and send that if the button is pressed and then after two cycles check if the button is still pressed. Otherwise we should just sleep. Yes that means we will not check to see if the button is pressed every cycle, but that is still perfectly valid.

This solution lowers the lines of code as well as energy consumption of the solution.

Third option

The last option is more expensive than the first two. But we can solve the puzzle with one line of code

We add a DX300 to the solution so we make an xbus signal (which I haven’t dived into yet) that will be 1 when the button is pressed otherwise it is zero. Then we just read that and use the gen instruction to make a pulse pulse of either 0 or 1 in length and then a low output for 1 cycle as well. Tada – minimum possible lines of code I have managed for the diagnostic pulse generator.

Posted by Kristian

Great solutions! I’m embarrassed how many lines it took me. Where in the game do we learn “gen” though? I’m just starting out and didn’t find it in the reference material.

Moctar Bebaha

I very much like your third option. It’s clever! Thanks for sharing it.
For the first option, I suggest the below modification. You will find its power usage is 40% lower that your option, because it avoids unnecessarily writing to the Pulse Output during the times when the Simple Input is 0.

teq p0 100
+ mov 100 p1
+ slp 1
+ mov 0 p1
slp 1

Ethan

Hi Kristian,

For the Diagnostic Pulse Generator, would you be able to tell me why this does not work?

teq p0 100
+ mov 100 p1
+ mov 0 p1
slp 1
teq p0 100
+ mov 0 p1
+ mov 100 p1
slp 1

Thanks

Michael

@Ethan
Your code does not work because it leaves the output at whatever level it was last set to, and doesn’t set it to 0 when the button is released. The following code does exactly what your code does:
teq p0 100
+ mov 0 p1
slp 1
teq p0 100
+ mov 100 p1
slp 1
This is because the processor walks through the code far faster than the time units involved. The first “+ mov” in each four lines of your code effectively does nothing, as it’s far too brief to have an effect on the output. Your code does alternate the output while the button is pressed, but whether it sets it to 0 or 100 the next time the button is pressed is a 50/50 chance depending on which code block it happens to be at by that time. That’s because you’re alternating through the same two blocks even when the button isn’t pressed.

toinetoine

@Ethan
This:
mov 100 p1
mov 0 p1
slp 1
Is the same as:
mov 0 p1
slp 1

All that matters is the last value sent to the pin before the sleep