• How to Expose a C Function up to JS Userspace on Tessel

    Wednesday, August 27, 2014

    8/27/2014– Jia Huang

    This document will be kept up to date on Github

    This tutorial goes over how to expose a C function to JS where the user can interact with it via any JS function.

    The function will pass this simple test case:

    var tessel = require('tessel');
    console.log("Can Tessel add?", 3 == tessel.add(1, 2));
    1. Clone down the tessel/firmware repo.
    2. Set up the firmware according to the tessel/firmware readme.
    3. Open up src/tessel.c. Add these lines

      uint32_t tessel_add(uint32_t x, uint32_t y)
          return x + y;
    4. Add this function to the header file. Open up src/tessel.h and add

      uint32_t tessel_add(uint32_t x, uint32_t y);
    5. Add the Lua binding. Open up src/hw/l_hw.c and add

      static int l_hw_add(lua_State* L)
          uint32_t x = (uint32_t)lua_tonumber(L, ARG1);
          uint32_t y = (uint32_t)lua_tonumber(L, ARG1+1);
          lua_pushnumber(L, tessel_add(x, y));
          return 1; // return 0 if the c function doesn't return a value
    6. Scroll down to the bottom of src/hw/l_hw.c where we’re defining all the JS function names in luaL_reg regs[] and add in the following entry:

      {"add", l_hw_add}

      So it should look something like:

      luaL_reg regs[] = {
          {"add", l_hw_add},
          // spi
          { "spi_initialize", l_hw_spi_initialize },
          { "spi_enable", l_hw_spi_enable },
    7. Add the JS bindings. Open up builtin/tessel.js and find this function:

      this.deviceId = function(){
          return hw.device_id();

      Add the following right below it

      this.add = function(x, y){ // the "this" object is referring to the "tessel" object
          return hw.add(x, y); // the "add" function here corresponds with the string in the lua binding. That's how we get from C -> Lua -> JS
    8. Go back to the main directory of the firmware repo and do a make arm. You should see an output like this

      [183/183] STAMP obj/tessel-firmware.actions_depends.stamp
      arm-none-eabi-size out/Release/tessel-firmware.elf out/Release/tessel-boot.elf out/Release/tessel-otp.elf
      text       data     bss     dec     hex filename
      824912     3576   24660  853148   d049c out/Release/tessel-firmware.elf
      30848      2260    3232   36340    8df4 out/Release/tessel-boot.elf
      6100      34272      36   40408    9dd8 out/Release/tessel-otp.elf

      This outputs the elf file for hardware debugging.

    9. Now go to out/Release/ and do an ls. You should see the following

      build.ninja              tessel-cc3k-patch.bin    tessel-firmware.bin.cpgz
      gen                      tessel-cc3k-patch.elf    tessel-firmware.elf
      obj                      tessel-erase.bin         tessel-firmware.hex
      tessel-boot.bin          tessel-erase.elf         tessel-otp.bin
      tessel-boot.elf          tessel-firmware.bin      tessel-otp.elf

      Here’s what each of those do:

      • tessel-boot: bootloader for Tessel. Also writes the Tessel version number (04) in otp.
      • tessel-cc3k-patch: updates the firmware for the CC3000 wifi chip on Tessel. Current version is 1.28.
      • tessel-erase: erases all JS user code on Tessel.
      • tessel-firmware: the firmware for Tessel. This was just changed this to add the ’.add’ function.
    10. Overwrite the Tessel firmware with the new firmware you just built. In the Release directory:

      tessel update ./tessel-firmware.bin Don’t forget that ./ before tessel-firmware. It specifies a local path. Otherwise tessel update will look for firmware patches on our build server.

    11. Now run the test code you have for this function and it should pass.

    If you want to revert back to the original Tessel firmware, just run a tessel update --force which will force Tessel to update to the newest release version.

    This document will be kept up to date on Github

    #tessel #c #js #javascript #compiler #native #lua #js on hardware #jia huang

  • Arduino <-> Tessel communication

    Thursday, August 21, 2014

    8/21/2014– Jia Huang

    This document will be kept up to date on Github

    This is a tutorial for how to pass data back and forth between an Arduino and a Tessel.

    The data is passed via a UART bridge. Arduino has the SoftwareSerial library for UART comm and Tessel has it’s built in UART functions.

    UART works through having TX (transmit) and RX (recieve) pins. A TX of one device is hooked up to the RX of another device like this:

    • Tessel TX Arduino RX
    • Tessel RX Arduino TX
    • Tessel GND Arduino GND

    Step 1: Get an Arduino

    The Arduino needs to operate at 3.3V. Some boards which operate at this voltage are:

    Both the Seeeduino and the Crowduino can switch between 5V and 3.3V.

    Arduino Uno

    Arduino Unos send over signals at 5V and this will damage Tessel. If you are planning on using an Arduino Uno, you need to make a 5V to 3.3V level converter which shifts the 5V UART TX signal from the Arduino to 3.3V.

    The UART TX coming from Tessel is at max 3.3V, but this will register as a digital “high” signal so it does not need to be boosted up to 5V.

    Step 2: Hook up the Arduino to the Tessel

    There are 3 pins that need to be hooked up, UART TX, UART RX, and Ground.

    In the code example, we’re going to be using Arduino’s SoftwareSerial on pins 10 and 11.

    wiring an arduino to a tessel

    • Arduino Pin 10 (orange wire) Tessel Port D, pin TX/G1
    • Arduino Pin 11 (white wire) Tessel Port D, pin RX/G2
    • Arduino Ground (brown wire) Tessel Ground

    Step 3: Program the Arduino

    Run this code on the Arduino

    #define rxPin 10 // connect to TX of other device
    #define txPin 11 // connect to RX of other device
    SoftwareSerial tesselBridge =  SoftwareSerial(rxPin, txPin);
    void setup()  
      // open serial port at 9600 baud
      Serial.println("Starting up...");
      // set the data rate for the SoftwareSerial port
    void loop() // run over and over
      if (tesselBridge.available())
      if (Serial.available())

    Step 4: Program Tessel

    Make a folder for the code:

    mkdir arduinoBridge;
    cd arduinoBridge; touch uart.js;

    Put this in the uart.js file.

    var tessel = require('tessel');
    var led1 = tessel.led[0].output(0);
    var led2 = tessel.led[1].output(0);
    var i = 0;
    // baudrate must match the baudrate set in the Arduino file
    uartBridge = tessel.port['D'].UART({baudrate: 9600}); 
    uartBridge.on('data', function(data){
      // UART data is not packetized, so you will get the data 
      // buffer as the message is sent. This means that long
      // messages will be truncated as several events.
      var number = parseInt(data[0]) - 48; // convert hex to ascii to int
      console.log("got data", data, number);
      if (number == 1)
      if (number == 2)
    // every 3 seconds write some data over to the arduino
      uartBridge.write("Hi there "+i+"\n");
    }, 3000);

    Run the code with tessel run uart.js, or if you want this to be persistent through power cycles, tessel push uart.js.

    Step 5: Test it

    You should be able to go into the Arduino console and see the blue and green LEDs on Tessel change as you enter a “1” or a “2”.


    This document will be kept up to date on Github

    #tessel #technical machine #arduino #uart #serial port #jia huang

  • Tessel Faster Better Stronger

    Wednesday, August 20, 2014

    8/20/2014– Nathan Lintz

    How do we make Tessel faster? How do we keep Tessel simple for users yet powerful enough to take on big problems? What does it take to make a bulletproof wifi connected microcontroller that can truly deliver on the promise of the Internet of Things? These were just a few of the questions which guided the projects I worked on the summer.

    To solve these sorts of problems, I focused on improving the speed of Tessel by writing new firmware apis and porting the Tessel platform to other chipsets. I learned a lot about developing hardware and software platforms, so I thought I’d share some of the insights I gained along the way.

    How Fast? This Fast

    Moving Pixels

    I was inspired to work on improving the Tessel’s performance after reading a request on our forums for an LCD screen module. I naively believed that getting the Tessel to cooperate with a screen would be as simple as porting a C graphics library to JavaScript and plugging in an LCD.

    My first attempt resulted in a graphics library which could output approximately 1 pixel a second. At this rate, filing a phone screen sized display would take approximately 100 hours…bummer. I profiled the program to find what was taking so long and it turned out that making a JavaScript call per pixel was causing the library’s performance to degrade dramatically.

    Not wanting to give up quite yet, I decided to dive into the firmware and see if there was any way to pump out pixels at a faster rate. I created a new hardware API for the Tessel, the SPI Batch API, which improved the performance of the graphics library I wrote by a factor of 400! With this new implementation we went from making one JS call per pixel to one JS call for the entire screen. When I tested the library, colorful pixels began pouring into the screen, proving that graphics programming is possible on the Tessel.

    Developing a graphics library and a firmware API for the Tessel taught me a lot about the power and limitations of JavaScript. When it comes to event driven programming and IO bound tasks, JavaScript is great. However, when it comes to matters of raw speed, C is usually the right answer. This insight can be distilled into the following heuristic which is applicable any time you’re writing code which involves hardware and software components:

    For CPU bound tasks, like pushing pixels to a buffer,write your code in C. For IO bound tasks, like reading from a file or handling HTTP requests, use a high level language like JavaScript.

    Portable Tessel - Modules Everywhere

    After modifying the Tessel firmware to handle graphics, I talked to the team about other ways we could improve Tessel’s performance. We realized that many of our problems could be solved by having an operating system. At the moment, Tessel doesn’t run an operating system; rather, it has a firmware layer which can run a single program. As a result, we can’t use libraries which rely on an OS. By running Tessel on a Linux board, we would have access to these sorts of libraries such as V8, Google’s JS engine, and the Linux TCP stack. This insight blossomed into the Portable Tessel Platform, a node package which emulates the Tessel API on a computer such as the Raspberry Pi or Cubieboard.

    Raspberry Pi


    I started off this project by writing up a spec and picking node libraries that would emulate the hardware APIs for the Tessel. Our modules each use either SPI, UART, GPIO pins, I2C, or some combination thereof. After some quick searching on NPM, I found found libraries which would implement the needed protocols.

    The libraries I found seemed to work, so I assumed that all I had to do was wire the boards to the modules. Unfortunately, I neglected to make sure that the hardware of the different boards was similar enough to the Tessel and that Linux fully supported all of the drivers I needed. I began testing some of our modules on the Raspberry Pi and Cubieboard, and I found that I2C on the Raspberry Pi has issues communicating with our modules, as its processor doesn’t support certain commands such as repeated start transfers. Similarly, the Cubieboard doesn’t have SPI support unless you recompile the kernel drivers.

    After discovering that the boards did not support the needed protocols, I began to research how other people got them working. It took a while, but eventually I found a way to properly compile the drivers for the Cubieboard and how to fix the I2C driver for Raspberry Pi. Once I had working drivers, I just had to hook up the boards to the Tessel modules and the Portable Tessel Platform was born. Now users can build projects using our hardware modules on their own boards, opening our platform up to people who haven’t purchased a Tessel yet.

    Working on the Portable Tessel Platform taught me a lot about the challenges of hardware-software integration. In pure software projects, it is easy to just swap out or modify source code to meet your needs. In hardware, planning out everything ahead is necessary as some boards not have all the features you need. I was lucky that I found new drivers for the Cubieboard and Raspberry Pi, but picking boards which have full support for SPI and I2C would have made building the Portable Tessel Platform much easier.

    Next year I’ll be back at college so you won’t be hearing from me on the blog for a while. Please message me @nlintz if you get a chance to build any exciting hardware projects on the Portable Tessel Platform or graphics projects using SPI Batch.

    Nathan Lintz

    #nathan lintz #tessel #technical machine #portable tessel platform #ptp #raspberry pi #cubieboard #portable #javascript #C #platform #performance #speed

  • Evan's Summer Internship Farewell

    Monday, August 18, 2014

    8/18/2014– Evan Simpson

    It feels like just last week that Jon turned to me in the car and asked, “now that you’re halfway through your internship, what do you think so far?” I then pointed out to him that I had only been at Technical Machine for three weeks, and had planned on staying for two more months, so I was nowhere near halfway done. I can’t really blame Jon for thinking I’d been there longer, since I joined during the busiest time of the company’s short history, when Tessel was getting ready to ship for the first time. That being said, I’m finding it hard to believe how quickly the remaining time has gone by.

    The work that I did for Technical Machine was so diverse that there was never a dull moment. I started with small module examples and README fixes, and went on to actually adding functionality to the module libraries, as well as fixing bugs. At one point I was making changes to the runtime, at another, firmware. From hardware debugging and module design to web server development, I’ve certainly had my fill of fun things to work on. Through all of this fun work, though, I did learn quite a bit in just these short months, and I’d like to share some of those things with you now.

    Internships Can be Meaningful Without Gimmicks

    I’ve seen and heard about too many different intern programs that will include things like field trips and fun events to make sure the interns have a good summer. While I do appreciate the intent of these activities, I feel that sometimes it is done as a way of saying “sorry the work isn’t very interesting, let’s take a break and have some fun”. Working at Technical Machine I realized that when the work itself is fun, those other perks and gimmicks don’t really seem all that special. What I wanted out of an internship was to work on something I enjoyed with other people, and to feel like my accomplishments mattered to the company. That’s exactly what I got here at Technical Machine, and I couldn’t have asked for more.

    Hardware Doesn’t Have to be Hard

    I’d say I had a very basic understanding of electronics and hardware development before joining Technical Machine, having only worked with Arduino on a handful of different projects. That quickly changed as I started to make changes to different module libraries. I became much more familiar with how microcontrollers load and run programs, and the different protocols devices use to talk to each other over, with or without wires. The thing that struck me the most was how simple it all was. Most of the devices we use today are all digital electronics, which coming from a background in software development, isn’t nearly as complex as I thought it all was. Putting a “digital-only” constraint on a system means that it can translate very well from the hardware domain into the software domain, where it can be abstracted and automated with ease.

    If you’re a software developer looking to learn more about hardware, I’d definitely recommend reading through some of the source code for some of the Tessel module libraries. They’re all written in JavaScript, so they’re easy to understand, but they also show you how the Tessel is communicating with the different modules. This also leads me straight into my next point…

    Open Source is Great

    Tessel is the first open source project I’ve ever contributed to, and I love it. I think there is a lot of good that can come from open source projects, whether they be based in software, hardware, data, or otherwise. Right now there isn’t nearly as much open source hardware as there is software, but there are still some good resources out there that are invaluable when it comes to starting a new hardware project. There were a few times when I was working on one of our modules and the best resources for debugging certain problems were other open source projects using similar parts.

    Now that I’m all done, it’s time for me to return to school for one more year. I had a great time out here and I plan to continue contributing to the project in my spare time, so expect to see me around on Github.

    See you around,
    - Evan

    P.S. If you’re interested in working or interning for Technical Machine, and want to know more about what it’s like day-to-day, let me know! I’d love to share more of my experiences.

    #evan simpson #internship #summer #summer intern #technical machine #tessel #open source #hardware

  • Getting the CC3000 working with JavaScript

    Friday, August 15, 2014

    8/15/2014– Jia Huang

    When Tessel’s wifi is connected the wifi chip’s features can be accessed through Node’s net and http libraries.

    However, there are a few features of the CC3000 that do not fit within Node’s API, such as the ability to connect to a network, or exposing to a user that their network connection has been dropped.

    We recently introduced the ability to control Tessel’s onboard wifi connections from JavaScript. It’s done through another library called wifi-cc3000 that now comes bundled on Tessel, much like the tessel library. It allows for something like this:

    var wifi = require('wifi-cc3000');
    // connect to a network
    function connect(){
        security: 'wpa2'
        , ssid: '#####' // network name
        , password: '#####'
        , timeout: 30 // in seconds
    // reconnect on dropped connection
    wifi.on('disconnect', function(err, data){
      console.log("disconnect emitted", err, data);
      connect(); // try to reconnect

    A more indepth example is on Tessel’s getting started page and the full documentation is on our docs page.

    How it’s implemented

    The technical details behind the wifi-cc3000 library are similar to how we expose other C functions to JS, with the exception of having to also work with the CC3000 wifi chip.

    TI gives out a closed source firmware binary that gets loaded on to the CC3000, along with the C libraries needed to communicate with the CC3000. This provides us the socket interface and CC3000 specific functions like network connection.

    It communicates over SPI, where our Tessel MCU acts as the master and the CC3000 is the slave device. In addition to the default SPI pins (clock, data in, data out, and slave select), it also has an interrupt pin (IRQ).

    An interrupt is raised by pulling the IRQ pin low, which triggers an interrupt on our main MCU. This allows our microcontroller to give the CC3000 a set of commands (like go connect to X network), and then go do other processing until the CC3000 responds with a connected or disconnected event.

    A typical call on the CC3000 looks like this:

    1. We call a CC3000 driver function.
    2. The command gets translated into a SPI signal which is passed to the CC3000.
    3. The CC3000 does some processing.
    4. The CC3000 fires an interrupt.
    5. We handle the interrupt by calling a CC3000 processing function to the interrupt handler.

    Some calls from the CC3000 are unsolicited, such as when we drop a wifi network. In this case the CC3000 directly fires an interrupt without us initiating the call.

    The wifi-cc3000 library needs to handle both types of calls:

    1. Calls which are initiated from the user, such as .connect.
    2. Unsolicited events from the CC3000, such as a disconnected event.

    In order to make this easier, we wrote some wrapper libraries.

    Calls initiated by the user

    Calls initiated from JS are similar to any other JS -> C exposure (like our Pin API for example). It usually follows these three steps:

    1. Bind C functions to Tessel’s VM functions. We have two locations for this, one in the runtime repo, and another in the firmware repo. The bindings on runtime relate to anything needed for Node compatibility (such as the `net` lib) while the ones in firmware relate to how Tessel specifically operates (such as Pin toggling and LEDs). Since the wifi commands we’re looking at (connect, disconnect, setting timeouts) are specific to the CC3000 and not to Node, the bindings are in the firmware repo. A typical binding looks like this:
         static int l_wifi_is_busy(lua_State* L) {
           lua_pushnumber(L, hw_net_inuse() ||  
               tessel_wifi_is_connecting() ? 1 : 0);
           return 1;
      This pushes a `1` into the global Lua context for this function’s return value if the wifi chip is in use, otherwise it pushes a `0`.
    2. Expose VM functions through a process binding to JS. All of our firmware’s hardware functions are bound to the `luaopen_hw` context. When Tessel first boots up we push in these functions into the VM.
    3. Wrap it in a JS library. We can link to a process binding in order to access the functions exposed through `hw`. This allows us to call C functions.
         self.isBusy = function(){
           return hw.wifi_is_busy() == 1 ? true : false;

    Unsolicited calls

    Unsolicited calls are more complicated since we’re going from C -> JS.

    All JS is handled inside of the event loop, so in order to surface up a call from C we have to wrap our C function as if it were an event and then push it to the head of the event queue.

    The process is:

    1. Create a tm_event from C. In this case it’s the disconnect event.
         tm_event wifi_disconnect_event = TM_EVENT_INIT(wifi_disconnect_callback);
    2. On the C callback that the CC3000 triggers, also trigger the tm_event.
         void _cc3000_cb_wifi_disconnect ()
    3. This pushes the event to the head of the event queue.
         void tm_event_trigger(tm_event* event) {
          if (event->pending == false) {
              event->pending = true;
              event->next = 0;
              if (event_queue_head) {
                  // Link it on to the end of the existing linked list
                  event_queue_tail->next = event;
                  event_queue_tail = event;
              } else {
                  event_queue_head = event_queue_tail = event;
    4. Push the event message on to the VM and clean up.
         void wifi_disconnect_callback(void) {
            lua_State* L = tm_lua_state;
            if (!L) return;
            lua_getglobal(L, "_colony_emit");
            lua_pushstring(L, "wifi_disconnect_complete");
            lua_pushnumber(L, 0);
            tm_checked_call(L, 2);
    5. Listen for the hardware process in JS.
         process.once('wifi_disconnect_complete', function(err, data){
              self.emit('disconnect', err, data);
              callback && callback();

    For those of you who are curious and want to see the implementation, here’s pull request #40, which has all the changes in order to get the wifi-cc3000 library functional.

    #Jia Huang #tessel #Technical Machine #cc3k #cc3000 #wifi #javascript #api

July 2017

February 2017

November 2016

October 2016

September 2016

August 2016

July 2016

June 2016

April 2016

March 2016

February 2016

November 2015

September 2015

August 2015

July 2015

June 2015

May 2015

March 2015

February 2015

January 2015

December 2014

November 2014

October 2014

September 2014

August 2014

July 2014

June 2014

May 2014

April 2014

March 2014

February 2014

January 2014

December 2013

November 2013

October 2013

September 2013

August 2013

July 2013