Wireless Game Controller

2022-02-17

Part of my journey through Shenzhen I/O

Problem: Given 4 simple inputs (x, y, a, and b) and a radio with a non-blocking XBus receiver (radio-rx) and an XBus transmitter (radio-tx), wait for a ping, and when in comes in, respond with a data packet representing the state of x, y, a, and b in the form (x, y, ab). x and y are joystick values, and ab is a function of the button inputs a and b. It has value 0 if no buttons are pressed, 1 if a is pressed, 2 if b is pressed, and 3 if both are pressed.

First Attempt

My strategy is to use an MC4000 to compose the a and b inputs into the correct value, and shuttle that over to an MC6000, which will handle listening for incoming packets and responding.

The MC4000 has the a and b button logic. It reads a on p0, b on p1, and pushes the value over XBus on x0:

  mov 0 acc
  teq p0 100
+ add 1
  teq p1 100
+ add 2
  mov acc x0
  slp 1

The MC6000 brings in the value of ab on x2, the value of x on p0, and the value of y on p1. It communicates with the radio to receive packets on x0 and send packets on x1.

  mov x2 acc
  teq x0 -1
- jmp end
  mov p0 x1
  mov p1 x1
  mov acc x1
end:
  slp 1

Cost is ¥8, power usage is 638, and it requires 14 lines of code. The code is a touch worse than average, the cost is about average, but the power consumption is really bad.

Second Attempt

The reason the power consumption is poor is because the MC4000 computes the output of ab regardless of whether the radio has requested a response. So my strategy to fix this is to propagate the request signal to the MC4000 somehow.

I decided to do this via a space XBus channel between the two chips (connecting x1 on the MC4000 to x3 on the MC6000), allowing the MC6000 to send a message of 1 if a request came through, and 0 if not. The MC6000 now looks like this:

  teq x0 -1
- mov 0 x3
- jmp end
  mov 1 x3
  mov p0 x1
  mov p1 x1
  mov x2 x1
end:
  slp 1

You can see on line 2 and 4, it now messages the MC4000 over x3, which is x1 on the MC4000, and is the first value it checks:

  teq x1 1
- jmp end
  mov p1 acc
  mul 2
  add p0
  dgt 2
  mov acc x0
end:
  slp 1

I had to tighen the logic around calculating ab, which I approached by removing the comparisons and using the raw values as much as possible.

Cost remains ¥8, power usage drops from 638 to 504, and it requires 16 lines of code (previously 14). The code remains worse than average, the cost is about average, and while the power consumption is improved, it's still worse than average.