+ return 0;
+}
+
+static int8_t
+robotsim_i2c_ballboard(uint8_t addr, uint8_t *buf, uint8_t size)
+{
+ void *void_cmd = buf;
+
+ switch (buf[0]) {
+ case I2C_CMD_BALLBOARD_SET_MODE:
+ {
+ struct i2c_cmd_ballboard_set_mode *cmd = void_cmd;
+ robotsim_i2c_ballboard_set_mode(cmd);
+ break;
+ }
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+static int8_t
+robotsim_i2c_cobboard(uint8_t addr, uint8_t *buf, uint8_t size)
+{
+ void *void_cmd = buf;
+
+ switch (buf[0]) {
+
+ case I2C_CMD_COBBOARD_SET_MODE:
+ {
+ struct i2c_cmd_cobboard_set_mode *cmd = void_cmd;
+ robotsim_i2c_cobboard_set_mode(cmd);
+ break;
+ }
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+int8_t
+robotsim_i2c(uint8_t addr, uint8_t *buf, uint8_t size)
+{
+ if (addr == I2C_BALLBOARD_ADDR)
+ return robotsim_i2c_ballboard(addr, buf, size);
+ else if (addr == I2C_COBBOARD_ADDR)
+ return robotsim_i2c_cobboard(addr, buf, size);
+ return 0;
+}
+
+static void beacon_update(void)
+{
+ uint8_t flags;
+ int16_t oppx, oppy;
+ double oppa, oppd;
+
+ IRQ_LOCK(flags);
+ if (ballboard.opponent_x == I2C_OPPONENT_NOT_THERE) {
+ IRQ_UNLOCK(flags);
+ return;
+ }
+ oppx = ballboard.opponent_x;
+ oppy = ballboard.opponent_y;
+ abs_xy_to_rel_da(oppx, oppy, &oppd, &oppa);
+ ballboard.opponent_a = DEG(oppa);
+ if (ballboard.opponent_a < 0)
+ ballboard.opponent_a += 360;
+ ballboard.opponent_d = oppd;
+ IRQ_UNLOCK(flags);