Skip to content

How to write module driver for Wio Link?

Jack Shao edited this page Jul 7, 2016 · 11 revisions

The Scene

A compatible module driver can be scanned by the server and be integrated into the online compilation service. The driver contributed by seeedstudio is written on top of suli - which is the HAL for various hardwares, here it's for esp8266 WiFi soc. The bottom level of HAL is based on the esp8266 Arduino project, thank you igrr and the contributors for that project.

Suli is currently in beta version and for internal usage, thus lack of documentations. It's easy to understand but if you feel not, you can definitely use the official SDK provided by espressif and the ESP8266 Arduino APIs. The version of espressif SDK used by Wio Link is 1.4.1.

The only difference between writing a Wio Link compatible driver and writing an Arduino compatible driver is that, you need to follow some rules to write the header file. It is for the scanning script to process it correctly. If you want to know more about the scanning process, please have a look at the "scan_drivers.py" source file.

Convention

  • Detailed file header with author email and license declaration
  • MIT License
  • Detailed function comment
  • Functions that serve for Constructor should start with the captial letter with Camel convention, e.g. MyClass
  • Functions and variables would be small cases concated with underscore, e.g. my_funtion, my_var
  • Indent with 4 spaces, no TAB
  • The best to use the standard data type with explicit length, e.g. int16_t, uint32_t

Rules for Writing Compatible Module Driver

  • File and directory naming

    • Small cases concated with underscore, if the driver is for grove modules, start with "grove_", e.g. grove_3axis_acc.h / grove_light_sensor.h / grove_nfc.h / grove_nfc (dir)
    • Recommend only one .h file, if more than one, the .h file end with "_class.h" will be searched first
  • Rules for .h file (see grove_example/grove_example.h for an example)

    • Must include a comment line that starts with "//GROVE_NAME" to specify the module name (even not a grove module), e.g. "//GROVE_NAME the-module-name"
    • Must include a comment line that starts with "//IF_TYPE" to specify the interface type, the value can be one of {GPIO, PWM, ANALOG, I2C, UART}, e.g. "//IF_TYPE GPIO"
    • Must include a comment line that starts with "//SKU" to specify a unique id of this module. For grove modules, this should be the SKU number, while for other modules this can be a UUID string.
    • Must include a comment line that starts with "//IMAGE_URL" to specify the URL of an image for this module.
    • Must include a comment line that starts with "//DESCRIPTION" to specify the brief description for this module, the description should be in one line.
    • Must include a comment line that starts with "//WIKI_URL" to specify the URL of the wiki page for this module.
    • Must include a comment line that starts with "//ADDED_AT" to specify the date at which the driver is uploaded.
    • Must include a comment line that starts with "//AUTHOR" to specify the name or/and email of the contributor(s) of this driver.
    • Must declare a class for this module
    • The only parameter(s) of the construct function should be hardware related, e.g. PIN number
    • The parameters' name of the construct function should follow the rule, refer to the next section "Parameters name of constructor"
    • All exposed output functions must be public and starts with "read_"
    • All exposed input/config functions must be public and starts with "write_"
    • All exposed input/output functions must return bool type
    • Private or internal functions MUST NOT start with "read_" or "write_"
    • All outputs of read_ functions must be returned with pointer data type.
    • read_ functions can be called with parameters too, the discrimination of input and output parameters is whether or not it's a pointer data type. Pointer type is fanout parameter.
    • The number of parameters for write/config functions MUST NOT exceed 4
    • The number of input parameters for read_ functions MUST NOT exceed 4
    • The data type of the parameters of expose functions should be one of {int, float, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t} and their pointer type. The pointer type is for outputting while the non-pointer type is for inputing (e.g. parameters for write_ functions and input parameters for read_ functions)
    • write_ functions support "char *" input parameters, but the limit is, only one "char *" parameter and MUST BE THE LAST PARAMETER and max length of the string is 256
    • The format of event declaration should be DEFINE_EVENT(event_name, event_data_type);, e.g DEFINE_EVENT(gesture, SULI_EDT_UINT8);, event_data_type can be one of SULI_EDT_BOOL, SULI_EDT_UINT8, SULI_EDT_INT8, SULI_EDT_UINT16, SULI_EDT_INT16, SULI_EDT_INT, SULI_EDT_UINT32, SULI_EDT_INT32, SULI_EDT_FLOAT, SULI_EDT_STRING
    • If an exposed function returned false, the error message can be collected. The error collection is done by the framework calling "char *get_last_error()" to get the string pointer. To describe the error message, you can declare a class member "char *error_desc" and assign a string to error_desc. And simply implement get_last_error like this: char *get_last_error() { return error_desc; };
  • Driver description lines

//GROVE_NAME        "Grove_Example"
//SKU               71714fec-8911-11e5-af63-feff819cdc9f
//IF_TYPE           GPIO
//IMAGE_URL         http://www.seeedstudio.com/depot/includes/templates/bootstrap/images/ico/grove.png
//DESCRIPTION       "The Grove Example is test driver for develop, not public."
//WIKI_URL          https://github.com/Seeed-Studio/Grove_Drivers_for_Wio/wiki/Grove_Example
//ADDED_AT          "2016-07-07"
//AUTHOR            "Your name or email here"

They're all sting values. Any of them which will probably contain space characters should be surrounded with double quotation mark. If you would like your copyright to be public (at the driver detail page of the App), you can modify the //AUTHOR comment line with your name or email.

  • Parameters name of constructor

    • GPIO module: the constructor parameter signature is (int pin)
    • ANALOG module: the constructor parameter signature is (int pin)
    • I2C module: the constructor parameter signature is (int pinsda, int pinscl)
    • UART module: the constructor parameter signature is (int pintx, int pinrx)
  • Comment for read_/write_ function

    • The function comment can be scanned into documentation which will be displayed in an API reference page
    • The function comment includes two sections, 1st is general description for this function, 2nd part is the description for parameters
    • The format of comment should be as following:
      • comment starts with "/**" and ends up with "*/"
      • general description can be multiple lines
      • @param description should finish in one line
/**
* general description here
* multiline description is allowed
* 
* @param total_led_cnt - the total count of this strip, max: 60
* @param rgb_hex_string - a rgb value in hex format, e.g. AA55CC (without # or 0x)
* 
* @return bool 
*/

Event Posting

After declared an event with DEFINE_EVENT Macro described above, you can post the event with the following Macros:

  • POST_EVENT(event_name, event_data_pointer);
  • POST_EVENT_IN_INSTANCE(grove_driver_class_instance, event_name, event_data_pointer);

event_name is the name of the event which is declared with DEFINE_EVENT in the header file.

event_data_pointer should be a pointer type that points to the event data. e.g. int32_t pos; ... POST_EVENT(encoder_position, &pos);

POST_EVENT_IN_INSTANCE is usually used in a interrupt handler or timer handler. e.g. https://github.com/Seeed-Studio/Grove_Drivers_for_Wio/blob/dev/grove_button/grove_button.cpp#L60

Example

Example Code of Grove Driver

How to self test?

###Step 1. Scan all the drivers into a database file.

Steps:

  • python envirenment is needed
  • cd project root dir (where the script scan_drivers.py lies)
  • run "python ./scan_drivers.py" in your shell or cmd line

You do not need to rerun the scanning if you haven't changed the header file of the driver(s).

###Step 2. Test building

With command line

With Mobile App

After step1 is done, the grove will be listed in the mobile app. Then you can drag this developing module onto some grove interface, then tap "Update Firmware" to test building. Please keep one thing in mind that every time you changed the driver's source code, you need to rerun the scanning process introduced in Step 1 to rebuild the static library which includes the compiled objects of all the grove drivers' code. To avoid this boring rescanning stuff, you can also modify the ALWAYS_BUILD_FROM_SRC variable in build_firmware.py to force the build always done on source code.

Where to Contribute?

Please pull request to this repo. https://github.com/Seeed-Studio/Grove_Drivers_for_Wio