Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow disabling parts of bootstrap at compile time #148

Open
matthijskooijman opened this issue Jun 30, 2014 · 4 comments
Open

Allow disabling parts of bootstrap at compile time #148

matthijskooijman opened this issue Jun 30, 2014 · 4 comments

Comments

@matthijskooijman
Copy link
Collaborator

As suggested in #142, it makes sense to disable parts of library-pinoccio or the Bootstrap sketch at compiletime. For the prebuilt Bootstrap firmware binaries, this isn't really an issue (until we hit the limits of the flash space), but for people making custom sketches that add a lot of code, having some relatively easy way to enable and disable parts of the code (lead scout support, timer3/servo support) makes sense.

To implement this, we'd ideally just use custom macros. However, the Arduino IDE doesn't currently support custom compiler options or defining macros as a sketch configuration, so we'd probably have to have some pinoccio-config.h that gets included from everywhere.

Also, splitting up Shell.cpp so that the definition of the bitlash commands can be more coupled with underlying code is probably useful in this regard.

@quartzjer
Copy link
Contributor

+1 on making Shell.cpp more modular, and perhaps having multiple firmware builds available to flash via HQ in some way too (and auto-build them all from a Makefile?)?

@amcjen
Copy link
Member

amcjen commented Jul 1, 2014

We had a hang to discuss how to make a proper modular class hierarchy for both backpacks and libraries like timer3 to be dynamically instantiated. I'll do my best to outline the result of that talk, to get your take @matthijskooijman, as well as the rest of the community:

Introduction of the term module

A module is a library that can be compiled into the Bootstrap sketch. It is very similar to an Arduino library, except that it is handled in a specific way by the Pinoccio handler class. Specifically, a module is registered with the Pinoccio class, where the handler will automatically call the setup() and loop() methods of each module.

pseudocode:

// Timer3.h
class Timer3 {
  public: 
    void setup();
    void loop();
// ...
};

// Timer3.cpp
Timer3::setup() {
   addBitlashFunction("timer3.init", (bitlash_function) timer3Init);
   // ...
}

Timer3 timer3;
Pinoccio.register(timer3);

Make backpacks a type of module

Right now backpack classes are their own thing in the Pinoccio source tree. The suggestion is made to make them just a type of module, which will let them be registered along with other modules. In addition, the backpack bus functionality can determine what backpacks are attached upon startup, and can dynamically instantiate the necessary objects for the backpack(s) attached. The same registration pattern will work for backpacks too.

pseudocode:

// EnvironmentalBackpack.h
class EnvironmentalBackpack {
  public:
    void setup();
    void loop();
  // ...
};

// EnvironmentalBackpack.cpp
EnvironmentalBackpack::setup() {
   addBitlashFunction("env.humidity", (bitlash_function) getHumidity);
   addBitlashFunction("env.lux.infrared", (bitlash_function) getIRLux);
   addBitlashFunction("env.lux.visible", (bitlash_function) getVisibleLux);
   // ...
}

// Backpacks.cpp
// Automatically called during Scout startup, when enumerating attached backpacks
void Backpacks::addBackpack(uint8_t *unique_id) {
   // ...
   Pinoccio.register(unique_id);
}

Make bridging work within a module

Modules that can bridge a troop to the internet are called bridging modules. Right now the only bridging modules are WiFi, but soon Bluetooth 4, Ethernet, and Cellular backpacks will exist that can bridge a troop to the web. A Field Scout attached to a computer via a USB cable can also act as a bridge, which is another special case of bridging, but with no backpack.

All modules that can bridge should have access to an object of type Stream, which inherits from Print, and defines essential methods like read(), write(), and available(). This object should be registered with the ScoutHandler.registerBridge() method, which will handle all bridging reading/writing when the module is loaded.

pseudocode:

// BLEBackpack.h
class BLEBackpack {
  public:
    void setup();
    void loop();
  protected:
    BLEClient client;  // type of Client, which is a subclass of Stream
  // ...
};

// BLEBackpack.cpp
BLEBackpack::setup() {
   client.init(...);
   Pinoccio.registerBridge(client);
   // ...
}

// Backpacks.cpp
// Automatically called during Scout startup, when enumerating attached backpacks
void Backpacks::addBackpack(uint8_t *unique_id) {
   // ...
   Pinoccio.register(unique_id);
}

@matthijskooijman
Copy link
Collaborator Author

Some thoughts:

  • Timer3 should probably inherit from a PinoccioModule class or something like that.
  • Registering a module (e.g. the Pinoccio.register(timer3); needs to happen automatically on startup, so the easiest way for that is to put it into a constructor. If we put it into the PinoccioModule constructor, then it doesn't even need to be called explicitely. Alternatively, we could have a PinoccioModuleRegister class, whose constructor takes a PinoccioModule object.
  • The PinoccioModule class should probably inherit from a ListItem class or something like that, which contains a next pointer so all registered modules can easily be put into a linked list, without having to allocate additional storage, or preallocate an array (which imposes a maximum number modules). See also http://stackoverflow.com/questions/24283277/merging-global-arrays-at-link-time-filling-a-global-array-from-multiple-compil
  • Module and backpack registration should be separate, as I think the example already shows. This allows a module to register multiple backpack types.
  • What does Pinoccio.register(unique_id); mean exactly? Does it ask the Pinoccio object to find the right Backpack subclass / instance for the unique id? Or is this part supposed to register the backpack type with the Pinoccio core? If so, why is it inside the Backpacks class?
  • If we want to support multiple backpacks of the same type, we should not register a Backpack object, but instead a BackpackFactory object (or function).

@amcjen
Copy link
Member

amcjen commented Jul 4, 2014

The first pass is up at #151

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants