Introduction

This is my very first project that I post here in Hackaday.io, it is about an old project revamped
recently that I am going to share here, besides on my channel in YouTube.

This system, that I called Network Shared Control (NSC) provides both event-driven execution and the ability to handle RPCs. I developed it in 2003 as an operating system and virtual machine, designed to operate on a series of devices built around the Atmel (now Microchip) ATmega32 (same family of Arduino's) microcontroller,  and sold the IP rights to a company that commercialized those products. In 2012 the company shut down and the exclusivity upon the rights dropped.
So, after having purchased a number of devices I also extended the system into a framework and wrote an AppWizard to create templates that can be directly written in C and compiled with the Imagecraft ICC AVR compiler (or avr-gcc by changing some parts).

In fact, the original system was designed to accepted only IL programs for the OS' virtual machine generated with a specific IDE, compiler and network deployment tool, that I developed too.

While currently the code is written for the ICC AVR compiler, it can be relatively easily ported for AVR-GCC, and the AppWizard is ready for generating also code for GCC, however at the moment the AppWizard is a legacy program made with Visual Basic (and VC++) even though it seems to work fine even in Windows 10.

Networking operations are supported through the SFBP protocol (it is a simple protocol that have a small payload, well suited for command-oriented, multidorp, half duplex, masterless communication over a serial line such as RS485), however it can be excluded or replaced with other modules, in fact I also have made, but not yet finished, a MIDI module to directly drive musical instruments.

Why event based programming?

Event driven programming is based on a paradigm where unlike linear programs that work executing tasks sequentially in a infinite loop, specialized functions are called by the underlying system when specific events happen, executing the tasks intended for that specific events.

This allows to write smaller, more efficient and less error prone programs.

They are particularly indicated for programs that need to react on external stimuli, allowing to avoid for polling those events, and making the program less complex and clumsy.

Why RPCs?

RPCs or Remote Procedure Calls are a mechanism that allows to call functions that are located into a physically different device, often at distance. This means that you can seamlessy write a program that run into a device A that interact directly with the functions you wrote for a device B, may be located 1 km each others ...or may be just few inches.

Unfamiliar with these concepts? I have made a series of videos to explain this system, this one is the first introcuctory part:

What can be used for

The framework can be used to develop single, stand alone, and distributed event based applications for embedded microcontrollers.

The devices that I have designed are controllers similar to Arduino, however they was not originally meant to host external extensions (shields), save some exceptions, and have full featured inputs (with decoupling and filtering) and outputs (open collector up to 40V 300mA, typically) and have an RS485L transceiver for field networking communication (up to 127 deices, up to 1 Km, bus and star mixed mode supported for short routes).

Some of them also have powerful relais on board (can withstand spikes up to 300A for few ms) while others have the ability to read analog inputs and one wire thermometers (DS1820) and iButton keys, or sport a display such as the LCDG that have a 64x128 display + 2 OC outputs + 3 logic inputs, analog input, thermometer, 4 keys keyboard and RTC crystal on board.

Finally these devices are ruggedly built with on board power supply that can accept from 8 to 28V dc, with reverse polarity protection and internal fuse. And indeed many units are still operating today in many installations both in home/building automation and in industrial applications and machines, proving to have a quite high MTBF (>9 yrs).

Example application are home automation systems, security, and machine control. I also made an intervalometer to synchronize stop-motion shots and dolly movements (for the production of puppet animations) with two units linked together; to control a robot, and more.

Robot's driver and control
Robot's driver and control: two NSC units talk each other and can receive messages from an external computer and an additional controller.

This is the schematic of the controller unit N68W that sports logic inputs, one wire inputs and OC outputs:

How to program Events and RPCs

As mentioned earlier event based programs execute tasks that are specific for each event those tasks are related to. This makes your program easier to write because your code just need to perform the required task. Let's see an example. Suppose you want to turn on and off an output upon each "click" event from an input. To accomplish this you just need to enter into the click (event) function the code required to check the current status of the output to change, swap it, and set the output:

event click(unsigned int Clicked) {
  // get the current status for output zero (OUT0)
  bool outputstatus = OUT(OUT0);

  // test if input zero has been 'clicked'
  if( TESTIO(Clicked, 0) ) { 
      // set output zero on if it was off, or viceversa
      setOut(this, 1, SETON(OUT0, !outputstatus) );
  }
}

The "click" event should be meant as the change in status of the input from low to high and then again to low, such as what would happen if we click a mouse button. The system provides four events for each logic input: input (on each inputs' change), click, longclick (a click hold for almost 3 seconds) and, where the physical input features this possibility, interrupt.

Remote Procedure Calls are as simple as events, actually in this system they are called public events, or pubevent. A public event is a function located into the code of one device that responds to calls coming from other devices. The way to do this is quite streightforward:

// on device A:
pubevent dosomething(byte caller) {
   // here the code to do something...
}

// on device B:
event click(unsigned int Clicked) {
   // call the function (public event) dosomething in device A:
   RPC( deviceA_dosomething_VECTOR );
}

There are some more things, though, such as defining the vectors and assigning vectors and function pointers to the vectors' table of the public events, but for that work the AppWizard comes in help.

Just keep in mind that, because protocol constraints, RPCs can carries no more than two integer (int) arguments or one integer and two bytes or four byte arguments (see the following table) and they work only if the SFBP module is not excluded.

No. Argumentsarguments (the 'caller' is always provided by the system)
None
byte caller
1
int, byte caller
2int, int, byte caller
3int, byte, byte, byte caller
4byte, byte, byte, byte, byte caller

Here is a video with more details on how an event-driven program + RPC can be made:


The system also provide a lot of other built-in functions, and in the case the device has a display, functions to display pages, move the next printing point, printing formatted numbers, and graphic bars are provided as well.



Some of the built-in functions



textOutprint a formatted string (page)
drawbardraw a bar
OUTretrieve the status of the logical outputs
getInretrieve the status of logical inputs (local or remote) or
analog inputs (local only)
setOutsets the status of logical outputs (local or remote) or
the modulation level for PWM outputs (local only)
getTimerretrieve the current time count of the specifier timer or
the date and time from the RTC
setTimersets a timer event (8 timers are available, resolution .1s
up to 6553.6 seconds; or resolution .01s up to 655.36 s)
Schedulermanages user's scheduled events on a
weekday 84600s basis
sendsends data over the network

Full list of functions

Built-in events

Let's see an example: How to make your own "hello world" application

This example shows step by step how to actually make a simple classic "hello world" application that will print on the screen of a LCDG (a device with display and controller), will allow to change the status of one output by showing a second page with captioned options by selecting a string to print from the global array of strings, and to commit the action to actually turn on or off the output zero (OUT0) driving a relay that in turn will turn on or off a desktop lamp.

I have put all the operations required into a video tutorial that you may see on my YouTube channel following this link: How to make your "hello world" application with the NSC framework and an LCDG display+controller device.


Conclusions

I do not know how many people will be interested in this project, at the moment I have not yet uploaded any file on Github, so let me know your opinions either by commenting here or aside the videos.

Thanks for your attention.