Clean up the basic codelab

The config was incomplete because it didn't include timing reports, and
wasn't even using the standard config process anyways. The comments were
also out of date due to the flatbuffers transition, and I added in a bit
more boilerplate in the RunIteration function, since handling the
flatbuffer builders is a bit less trivial than the queues were.

Change-Id: I6a9b12ca6c925b561211937fcf36d932299946d2
diff --git a/frc971/codelab/BUILD b/frc971/codelab/BUILD
index 6302443..ac0b80c 100644
--- a/frc971/codelab/BUILD
+++ b/frc971/codelab/BUILD
@@ -1,14 +1,19 @@
 package(default_visibility = ["//visibility:public"])
 
 load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
+load("//aos:config.bzl", "aos_config")
 
 cc_binary(
     name = "basic_test",
     testonly = 1,
     srcs = ["basic_test.cc"],
+    data = [":config.json"],
     deps = [
         ":basic",
-        ":basic_fbs",
+        ":basic_goal_fbs",
+        ":basic_output_fbs",
+        ":basic_position_fbs",
+        ":basic_status_fbs",
         "//aos/controls:control_loop_test",
         "//aos/events:shm_event_loop",
         "//aos/testing:googletest",
@@ -22,14 +27,56 @@
     srcs = ["basic.cc"],
     hdrs = ["basic.h"],
     deps = [
-        ":basic_fbs",
+        ":basic_goal_fbs",
+        ":basic_output_fbs",
+        ":basic_position_fbs",
+        ":basic_status_fbs",
         "//aos/controls:control_loop",
     ],
 )
 
 flatbuffer_cc_library(
-    name = "basic_fbs",
+    name = "basic_goal_fbs",
     srcs = [
-        "basic.fbs",
+        "basic_goal.fbs",
+    ],
+    gen_reflections = 1,
+)
+
+flatbuffer_cc_library(
+    name = "basic_output_fbs",
+    srcs = [
+        "basic_output.fbs",
+    ],
+    gen_reflections = 1,
+)
+
+flatbuffer_cc_library(
+    name = "basic_status_fbs",
+    srcs = [
+        "basic_status.fbs",
+    ],
+    gen_reflections = 1,
+)
+
+flatbuffer_cc_library(
+    name = "basic_position_fbs",
+    srcs = [
+        "basic_position.fbs",
+    ],
+    gen_reflections = 1,
+)
+
+aos_config(
+    name = "config",
+    src = "codelab.json",
+    flatbuffers = [
+        ":basic_goal_fbs",
+        ":basic_position_fbs",
+        ":basic_status_fbs",
+        ":basic_output_fbs",
+    ],
+    deps = [
+        "//aos/robot_state:config",
     ],
 )
diff --git a/frc971/codelab/README.md b/frc971/codelab/README.md
new file mode 100644
index 0000000..e274f24
--- /dev/null
+++ b/frc971/codelab/README.md
@@ -0,0 +1,7 @@
+# FRC971 "Codelab"
+
+Welcome! This folder contains a "codelab" where you can go through the process
+of fleshing out a basic control-loop using the same infrastructure as we do for
+the control loops that normally run on our robots. Currently, this just consists
+of a single codelab; the instructions for this are in the comments of the
+`basic.h` file in this directory.
diff --git a/frc971/codelab/basic.cc b/frc971/codelab/basic.cc
index 29ffcf5..36e64c5 100644
--- a/frc971/codelab/basic.cc
+++ b/frc971/codelab/basic.cc
@@ -15,7 +15,25 @@
   // the motor to anything but 0 V when the limit_sensor is pressed.
 
   // Ignore: These are to avoid clang warnings.
-  (void)goal, (void)position, (void)output, (void)status;
+  (void)goal, (void)position;
+
+  if (output) {
+    Output::Builder builder = output->MakeBuilder<Output>();
+    // TODO(you): Fill out the voltage with a real voltage based on the
+    // Goal/Position messages.
+    builder.add_intake_voltage(0.0);
+
+    output->Send(builder.Finish());
+  }
+
+  if (status) {
+    Status::Builder builder = status->MakeBuilder<Status>();
+    // TODO(you): Fill out the Status message! In order to populate fields, use
+    // the add_field_name() method on the builder, just like we do with the
+    // Output message above.
+
+    status->Send(builder.Finish());
+  }
 }
 
 }  // namespace codelab
diff --git a/frc971/codelab/basic.fbs b/frc971/codelab/basic.fbs
deleted file mode 100644
index 82c9607..0000000
--- a/frc971/codelab/basic.fbs
+++ /dev/null
@@ -1,35 +0,0 @@
-namespace frc971.codelab;
-
-// The theme of this basic test is a simple intake system.
-//
-// The system will have a motor driven by the voltage returned
-// by output, and then eventually this motor, when run enough,
-// will trigger the limit_sensor. The hypothetical motor should shut
-// off in that hypothetical situation to avoid hypothetical burnout.
-table Goal {
-  // The control loop needs to intake now.
-  intake:bool;
-}
-
-table Position {
-  // This is a potential incoming sensor value letting us know
-  // if we need to be intaking.
-  limit_sensor:bool;
-}
-
-table Status {
-  // Lets consumers of basic_queue.status know if
-  // the requested intake is finished.
-  intake_complete:bool;
-}
-
-table Output {
-  // This would be set up to drive a hypothetical motor that would
-  // hope to intake something.
-  intake_voltage:double;
-}
-
-root_type Goal;
-root_type Position;
-root_type Status;
-root_type Output;
diff --git a/frc971/codelab/basic.h b/frc971/codelab/basic.h
index acaec0c..944048f 100644
--- a/frc971/codelab/basic.h
+++ b/frc971/codelab/basic.h
@@ -4,7 +4,10 @@
 #include "aos/controls/control_loop.h"
 #include "aos/time/time.h"
 
-#include "frc971/codelab/basic_generated.h"
+#include "frc971/codelab/basic_goal_generated.h"
+#include "frc971/codelab/basic_output_generated.h"
+#include "frc971/codelab/basic_position_generated.h"
+#include "frc971/codelab/basic_status_generated.h"
 
 namespace frc971 {
 namespace codelab {
@@ -18,29 +21,33 @@
 //  $ bazel run //frc971/codelab:basic_test -- --gtest_color=yes
 //
 // Control loops all follow the same convention:
-//  There are 4 queues (goal, position, status, output).
+//  There are 4 channels (goal, position, status, output).
 //
-//  2 queues are input queues: goal, position.
-//  2 queues are output queues: output, status.
+//  2 channels are input channels: goal, position.
+//  2 channels are output channels: output, status.
 //
 // ::aos::controls::ControlLoop is a helper class that takes
-// a queue_group type from a .h file, and organizes to call
-// RunIteration() at a consistent interval. It will fetch from
-// goal and position messages from the goal and position queue,
-// and publish an output and status result to the output and status
-// queues.
+// all the channel types as template parameters and then calls
+// RunIteration() whenever a Position message is received.
+// It will pass in the Position message and most recent Goal message
+// and provide Builders that the RunIteration method should use to
+// construct and send output/status messages.
 //
-// The basic.q file will construct boilerplate c++ code for the
-// Goal, Position, Status, Message
-// types, and construct static variables for fetching these named queues.
-// Inquisitive souls can check out:
-//  $ bazel build //frc971/codelab:basic_queue
-//  $ vim bazel-genfiles/frc971/codelab/basic.q.{cc,h} -o
-//  from the 971-Robot-Code directory.
+// The various basic_*.fbs files define the  Goal, Position, Status, and Output
+// messages.
 //
-// Order of approaching this should be:
-// - Read the BUILD file and learn about what code is being generated.
-// - Read basic.q, and familiarize yourself on the inputs and types involved.
+// In order to get the tests to pass, you'll need to fill out the RunIteration()
+// implementation in basic.cc so that it uses the input goal/position to
+// meaningfully populate the output/status messages. You can find descriptions
+// of exactly what the fields of the messages mean by reading all the *.fbs
+// files, and the tests below can be reviewed to help understand exactly what
+// behavior is expected.
+//
+// Once you can get the tests to pass, follow the directions in the
+// documentation/tutorials/submitting-code-for-a-review.md file for creating a
+// code review of this change. We will not actually *submit* the change (since
+// that  would remove the challenge for future students), but we will go through
+// the code review process.
 class Basic
     : public ::aos::controls::ControlLoop<Goal, Position, Status, Output> {
  public:
diff --git a/frc971/codelab/basic_goal.fbs b/frc971/codelab/basic_goal.fbs
new file mode 100644
index 0000000..cfde3ba
--- /dev/null
+++ b/frc971/codelab/basic_goal.fbs
@@ -0,0 +1,11 @@
+namespace frc971.codelab;
+
+// This is the goal message for the subsystem--it will be sent irregularly and
+// is used to specify what the subsystem should be doing.
+table Goal {
+  // If set to true, the intake should turn on the motor and run until the
+  // limit sensor in the Position message turns on.
+  intake:bool;
+}
+
+root_type Goal;
diff --git a/frc971/codelab/basic_output.fbs b/frc971/codelab/basic_output.fbs
new file mode 100644
index 0000000..7f3b0b9
--- /dev/null
+++ b/frc971/codelab/basic_output.fbs
@@ -0,0 +1,11 @@
+namespace frc971.codelab;
+
+table Output {
+  // This would be set up to drive a hypothetical motor that would
+  // hope to intake something. Voltages on our robots generally range from
+  // -12.0 V to +12.0V. In this case, the intake should be commanded to actually
+  // intake by setting the voltage to 12 V.
+  intake_voltage:double;
+}
+
+root_type Output;
diff --git a/frc971/codelab/basic_position.fbs b/frc971/codelab/basic_position.fbs
new file mode 100644
index 0000000..1420313
--- /dev/null
+++ b/frc971/codelab/basic_position.fbs
@@ -0,0 +1,12 @@
+namespace frc971.codelab;
+
+table Position {
+  // The limit sensor being set to true indicates that we should stop turning on
+  // the intake motors--in a real robot, we might have an intake that pulls a
+  // ball in, and the ball then hits a limit sensor when it is fully contained.
+  // We would then want to stop running the intake to avoid spinning the intake
+  // against the ball.
+  limit_sensor: bool;
+}
+
+root_type Position;
diff --git a/frc971/codelab/basic_status.fbs b/frc971/codelab/basic_status.fbs
new file mode 100644
index 0000000..ec754b4
--- /dev/null
+++ b/frc971/codelab/basic_status.fbs
@@ -0,0 +1,11 @@
+namespace frc971.codelab;
+
+table Status {
+  // Lets consumers of Status know if the requested intake is finished. Should
+  // be set to true by the intake subsystem when the Goal message is requesting
+  // the intake to be on and the limit sensor from the position message has
+  // been enabled.
+  intake_complete:bool;
+}
+
+root_type Status;
diff --git a/frc971/codelab/basic_test.cc b/frc971/codelab/basic_test.cc
index fcb0f15..65ac625 100644
--- a/frc971/codelab/basic_test.cc
+++ b/frc971/codelab/basic_test.cc
@@ -7,7 +7,10 @@
 
 #include "aos/controls/control_loop_test.h"
 #include "aos/events/shm_event_loop.h"
-#include "frc971/codelab/basic_generated.h"
+#include "frc971/codelab/basic_goal_generated.h"
+#include "frc971/codelab/basic_output_generated.h"
+#include "frc971/codelab/basic_position_generated.h"
+#include "frc971/codelab/basic_status_generated.h"
 #include "frc971/control_loops/team_number_test_environment.h"
 #include "gtest/gtest.h"
 
@@ -82,38 +85,7 @@
  public:
   BasicControlLoopTest()
       : ::aos::testing::ControlLoopTest(
-            "{\n"
-            "  \"channels\": [ \n"
-            "    {\n"
-            "      \"name\": \"/aos\",\n"
-            "      \"type\": \"aos.JoystickState\"\n"
-            "    },\n"
-            "    {\n"
-            "      \"name\": \"/aos\",\n"
-            "      \"type\": \"aos.LogMessageFbs\"\n"
-            "    },\n"
-            "    {\n"
-            "      \"name\": \"/aos\",\n"
-            "      \"type\": \"aos.RobotState\"\n"
-            "    },\n"
-            "    {\n"
-            "      \"name\": \"/codelab\",\n"
-            "      \"type\": \"frc971.codelab.Goal\"\n"
-            "    },\n"
-            "    {\n"
-            "      \"name\": \"/codelab\",\n"
-            "      \"type\": \"frc971.codelab.Output\"\n"
-            "    },\n"
-            "    {\n"
-            "      \"name\": \"/codelab\",\n"
-            "      \"type\": \"frc971.codelab.Status\"\n"
-            "    },\n"
-            "    {\n"
-            "      \"name\": \"/codelab\",\n"
-            "      \"type\": \"frc971.codelab.Position\"\n"
-            "    }\n"
-            "  ]\n"
-            "}\n",
+            aos::configuration::ReadConfig("frc971/codelab/config.json"),
             chrono::microseconds(5050)),
         test_event_loop_(MakeEventLoop("test")),
         goal_sender_(test_event_loop_->MakeSender<Goal>("/codelab")),
@@ -124,6 +96,7 @@
         basic_simulation_event_loop_(MakeEventLoop("simulation")),
         basic_simulation_(basic_simulation_event_loop_.get(), dt()) {
     set_team_id(control_loops::testing::kTeamNumber);
+    SetEnabled(true);
   }
 
   ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
diff --git a/frc971/codelab/codelab.json b/frc971/codelab/codelab.json
new file mode 100644
index 0000000..dedb19f
--- /dev/null
+++ b/frc971/codelab/codelab.json
@@ -0,0 +1,23 @@
+{
+  "channels": [
+    {
+      "name": "/codelab",
+      "type": "frc971.codelab.Goal"
+    },
+    {
+      "name": "/codelab",
+      "type": "frc971.codelab.Output"
+    },
+    {
+      "name": "/codelab",
+      "type": "frc971.codelab.Status"
+    },
+    {
+      "name": "/codelab",
+      "type": "frc971.codelab.Position"
+    }
+  ],
+  "imports": [
+     "../../aos/robot_state/robot_state_config.json"
+  ]
+}