A Circular Reference

Adventures of a vagabond electron.

Using GCC and Clang With Eclipse on Windows

| Comments

Running GCC or Clang on Windows has never been easier thanks to the MSYS2 project. Setting up the Eclipse CDT environment to use these compilers is also very easy. This post will illustrate exactly how easy it is.

Installing MSYS2

  • Head over to the MSYS2 website and follow steps 1 - 7. At the end of it you should have a working MSYS2 shell.

  • Next you need to install GCC + other utilities (MAKE, GDB, BINUTILS, … etc) for windows. The Mingw-64 project provides versions of GCC that are capable of running natively on Windows and building Windows 64/32 bit target binaries, and MSYS2 has great support for mingw-64. Download the mingw64 packages using the MSYS2 package manager pacman.

There are a couple of ways to go about this - you can either download the individual packages (gcc, gdb …) or you can download all the relevant packages in one shot using the mingw-w64-x86_64-toolchain or mingw-w64-i686-toolchain depending on what you want to use. You can search the available packages using the command pacman -Ss string_to_search.

1
2
3
4
# This should install the toolchain into the /msys64/mingw64 folder
pacman -S mingw-w64-x86_64-toolchain
# Install make if it's not already installed. Eclipse will use make to run it's autogenerated makefiles. It goes into the /usr/bin directory
pacman -S make

Once this is done you will have a new shell in the /msys64 folder called mingw64.exe or mingw32.exe (if you installed the i686 toolchain). Runnnig this shell and typing gcc -v will give you some information on what you have installed. This shell can also be used to directly compile any makefile projects you have. Next we talk about integration with the Eclipse IDE.

GCC with Eclipse

Assuming you have already installed the Eclipse IDE for C/C++ developers. Eclipse has some built-in support for Mingw projects which depends on the presence of some environment variables like MINGW_HOME, MSYS_HOME etc. However the method I outline here is not related to this and is (imho) simpler and more robust.

In eclipse go to File | New | C Project | and select either Cross GCC or MinGW GCC project. Then in the project properties go to C/C++ Build | Environment

  • Select the option to “Replace native environment with specified one”. This is a really useful option that allows you to customize the environment for this build without having any dependencies on the system PATH.

  • Set the PATH variable to have access to the relevant gcc and make binaries. MSYS2 installs make in the /usr/bin directory and the gcc executables are in either mingw64/bin or mingw32/bin.

  • Define a TMP variable to point to the system TMP environment variable by using the syntax ${env_var:TMP}

image

Now you have configured the build environment. All that’s remaining is to setup the compiler and linker options. Go to C/C++ Build | Settings | Tool Settings | Cross GCC Compiler and set the command to gcc. Similarly set the Cross GCC Linker command to gcc. The Cross GCC Assembler command should be as.

Thats it! Select apply and build the project.

image

image

If you wan to use GDB, you need to create an Eclipse debug configuration.

Clang with Eclipse

MSYS2 provides packages for Clang also (mingw-w64-x86_64-clang and mingw-w64-i686-clang). There seem to be some dependencies with mingw, so you are better off first installing mingw first followed by clang.

Thereafter the settings are exactly the same as above except that this time instead of gcc you type clang for the compiler and linker commands. The assembler is llvm-as. lldb is not yet part of the MSYS2 package, so you can’t run the debugger yet; but you might be able to run gdb.

C Tips and Tricks[0]

| Comments

These posts document some of the C concepts that I often forget or confound and some idioms that I’ve encountered. It is intended as a quick reference (for myself). Most of it is not original work, some relevant sources can be found in the inline references, others might be burried in my subconscious.

Arrays

Whenever an array name appears in an expression except as the operand of unary & or the sizeof operator, the value of the array name becomes a pointer to the first element of the array.

1
2
3
4
5
6
int a[10];
int (*p_a)[10] = &a;	// &a is a pointer to an array of int with bounds 10, i.e. p_a = &a[0];
int *p_int = a;			// a is a pointer to int, i.e. p_int = &a[0]

int b[10][20];
int (*p_b)[20] = b;		// b is a pointer to an array of 20 ints, i.e. p_b = &b[0];

Arrays as function parameters

You can declare functions with array parameters, this is exactly equivalent to using the more common pointer syntax. The type qualifiers following the [ act as if they followed the * when the parameter’s type is rewritten as a pointer type. You can also use the static keyword within the [] to specify a minimum size for the caller passed array pointer. Thus:

1
2
3
int foo(int a[n]);  // is the same as foo(int* a)
int f(float array[const restrict]); // can be read as int f(float *const restrict array);
void foo(int a[static 10]); //  actual argument corresponding to a must be an array with at least 10 elements

Multidimensional arrays (Variable Length)

In C90 multidimensional arrays can be used with the convinent [i][j][k] indexing syntax only if the total size of N-1 dimensions (bounds a.k.a stride) are known at compile time. You don’t need to know the size of the last dimension as the stride of this dimension is equal to the sizeof(array_element_type). C99 created VLAs to overcome this restriction. Arrays whose size is determined at runtime are called Variable Length Arrays (VLA).

1
2
3
4
5
6
7
8
9
10
11
12
// C90 multidimensional arrays (using a single dimension array)
float a[m*n*sizeof(float)];
for (i = 0; i < m; ++i)
  for (j = 0; j < n; ++j)
	a[i*n + j] = 1.0;

// C99 multidimensional indexing
float a[m][n];
int i, j;
for (i = 0; i < m; ++i)
  for (j = 0; j < n; ++j)
	a[i][j] = 1.0;

References:

Randy Meyers has a series of informative articles in the now defunct C/C++ Users Journal that discuss VLAs and other topics summarized on this page in more detail. The journal arcives are available here. Dr.Dobb’s journal (also defunct) has copies of the articles too. VLA Part 1 VLA Part 2 VLA Part 3 VLA Part 4

C99 C99 Rationale C11 Final Draft

Strings

String literals v/s arrays

A string in C is simply an array of chars terminated by a '\0'. Initialized strings can be created in two ways - one is to statially allocate them in memory and hold a pointer to address where the string is stored, and the other is to store the string as an array of chars. In the first case they are constant and it’s undefined behavior to modify them, while in the second case their contents can be modified [C99 N1256 draft 6.7.8/32 “Initialization”].

1
2
3
/* pChar is a pointer to the actual lccation of the string, so we require an additional 4 bytes or more to store the pointer compared to string[] */
char* pChar = "I'm a string literal, I can be modified but no guarantees on the result"; // This always goes into the data segment
char string[] = "I'm a string array, can I be modified?"; // This could go into the stack or data segment depending on where it's defined

Anonymous string literals can also be used as in printf("Another literal"), in this case the pointer to the literal is implicitly passed to printf() on the stack. This by default allocation of debugging strings into data memory eat up a lot of useful RAM. Some targets have a way to relocate strings into program memory, for example AVR has the PROGMEM keyword which the Arduino platform extended to the F(x) macro.

Another trick is to use the C99 compound literal sytax to convert the string literal into a char array and push it onto the stack. However this trick only works for short length string literals, larger literals are stored in the data segment and then coped onto the stack at runtime by your smart ass compiler. The boundary was 18 bytes on an embedded MCU I tested with.

1
2
3
4
5
6
7
8
9
// AVR specific redirection into flash
#define PSTR(s) ((const PROGMEM char *)(s))

// Convert a string literal into an unnamed char array
printf("%s", (char []){"This is a string array stored on the stack"});
// A macro to do this
#define F(x)	(char []){x}
// A string with extended ascii chars
char ex = "An ex char to end it \xB0";

Jagged char arrays

C does not natively support jagged arrays but you can declare an array of variable length strings like:

1
2
char* pChar2D[] = {"A long long long string", "short", "something else"};
printf(pChar2D[0]); // A long long long string

How does it work? Relook at the declreation of pChar2D- it is an array of pointers to char, which means that when you say pChar2D[0] you end up getting the address of the string literal "A long long long string". Not surprisingly, this is exactly how jagged arrays of other types are programatically dealt with usually. i.e.

1
2
3
4
int r0[] = malloc(sizeof(int) * 10);
int r1[] = malloc(sizeof(int) * 2);;
int *jagged[] = { r0, r1 };
printf("%d %d, jagged[0][9], jagged[1][1]);

If you are unsure about a C declerations, they can be looked up at cdecl.org

Designated Initializers

Initializing individual elements with arrays and structs can be done with designated initializers. Elements that are not specifically initialized are automatically initialized to 0. This is clearly better than the old method of having to initialize members individually which lends garbage values to uninitialized elements. More details here

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Initializing an array
int a[100] = {[0]=5, [99]=100};

// Struct
struct S1 {
  int i;
  float f;
  int a[2];
};

struct S1 x = {
  .f=3.1,
  .i=2,
  .a[1]=9
};

Compound literals

Just like how like languages like C# allow you to create and manipulate anonymous objects, C99 allows you to do the same thing with C types like int, struct, union, array etc. These are called compound literals. You are allowed to take the address of these constants and pass them around as function parameters. The basic syntax is (<type>){<initializer-list-expression>}.

1
2
3
4
(float){3.14};
(struct POINT){10, 10};
(char []){"Compound Literal Array"};
(const char[]){"A CONSTANT compound literal array"};

Drawing Anti-aliased Circular Points Using OpenGL/WebGL

| Comments

This article explores points in OpenGL, and I use WebGL to illustrate the concepts. The demos may not render in Internet Explorer as I use new ECMA Script 6 syntax for strings (storing the shader code) which apparently is not supported by IE.

Drawing a Point

If you discount the WebGL boilerplate code, drawing a point is easy. Attributes to the vertex shader are a vec3 point position, vec4 color of the point and a float point size. The shader updates the OpenGL built-in variables gl_Position and gl_PointSize from this and passes the color as a varying to the fragment shader. The fragment shader simply outputs the color it got from the vertex shader. Note that the maximum Point Size for WebGL is only guaranteed to be at least equal to 1 pixel, though in most cases it’s more than one.

[Our simple vertex shader] [lang : c] (vs-points.js) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var vs_points = `
attribute vec3 vPosition;
attribute vec4 vRgbaColor;
attribute float vPointSize;
varying  vec4 color;

void
main()
{
    gl_Position =  vec4(vPosition, 1.0);
	//gl_PointSize = 10.0;
	gl_PointSize = vPointSize;
    color = vRgbaColor;
	//color = vec4(1.0,0.0,0.0,1.0);
}`;
[Our simple fragment shader] [lang : c] (fs_point_default.js) download
1
2
3
4
5
6
7
8
9
10
var fs_point_default = `
precision mediump float;
varying  vec4 color;

void
main()
{
    float alpha = 1.0;
    gl_FragColor = color * (alpha);
}`;

I will ignore the boilerplate code as there’s nothing special about it. You can figure it out by just going through the points.js script. The relevant high-level code is shown below:

1
2
3
4
5
6
7
8
9
10
11
  var point = [0.0, 0.0, 0.0];
  var color = [1.0, 0.0, 0.0, 1.0];
  var size = [400.0];

  var canvas = document.getElementById("point-canvas");
  initGL(canvas);
  shaderPointDefault = initShaders(0);
  initBuffers(point, color, size);
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  gl.enable(gl.DEPTH_TEST);
  drawScene(shaderPointDefault);

The result of this is - a nice big square!

Drawing a disk

To get a circle out of this square we need to first understand the square better. An important parameter is gl_PointCoord. This is available at the Fragment Shader and tells the location of the current fragment inside the current point. The idea is that depending on the value of gl_PointSize, a point will be actually composed of many pixel fragments and this parameter allows us to identify each of these fragments. Using this information we can draw any figure inside a “point”.

Now gl_PointCoord has an X and Y coordinate and varies from $ [0,1] $ just like a 2D texture. Recall that the equation of a circle with origin at the center and radius 1 unit is

This is the same as the dot product of the 2D vector with itself. Since GLSL provides us a dot() function, we can draw a circle in the square by coloring the region in space where the dot product of a vector with itself is $ <= 1 $:

[Extract a circle from a point] [lang : c] (fs_point_alias.js) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var fs_point_alias = `
precision mediump float;
varying  vec4 color;

void
main()
{
    float r = 0.0, delta = 0.0, alpha = 1.0;
    vec2 cxy = 2.0 * gl_PointCoord - 1.0;
    r = dot(cxy, cxy);
    if (r > 1.0) {
        discard;
    }
    gl_FragColor = color * (alpha);
}`;

All pixels outside the radius of 1 are discarded. The result is:

Since we discard all pixels outside the radius, you can see that the edges are rough and aliasing is pretty bad. Use the CNTL + keys to zoom into the web page to see the distortion better.

Anti-aliasing the disk

Instead of abruptly discarding the pixels at the fragments where $ r > 1 $, we need to smooth out the colors at the edge pixels. One way to do this is to use the smoothstep() function provided by GLSL that allows you to interpolate the value of a step function in the region where the independent variable lies between the min and max values. In the case of a normal step function that we indirectly used before, the min and max was $ [1,1] $ respectively - anything greater than 1 is clipped to 1 and anything less than 1 is clipped to 0. To use smoothstep, we need to find an $ \epsilon $ so that we can define a range of $ [1+\epsilon, 1-\epsilon] $ overwhich the color of the fragments can be smoothed.

The GLSL fwidth() function can give us this information. It returns the maximum change in a given fragment shader variable in the neighbourhood of the current pixel (8 surrounding pixels). So fwidth(r) gives us the $ \epsilon $ and we can have a shader as:

[Our simple vertex shader] [lang : c] (fs_point_anti_alias.js) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var fs_point_anti_alias = `
#ifdef GL_OES_standard_derivatives
#extension GL_OES_standard_derivatives : enable
#endif

precision mediump float;
varying  vec4 color;

void main()
{
    float r = 0.0, delta = 0.0, alpha = 1.0;
    vec2 cxy = 2.0 * gl_PointCoord - 1.0;
    r = dot(cxy, cxy);
#ifdef GL_OES_standard_derivatives
    delta = fwidth(r);
    alpha = 1.0 - smoothstep(1.0 - delta, 1.0 + delta, r);
#endif

gl_FragColor = color * alpha;

}`;

And now we finally have a lovely circle.

A demo to put it together

The below demo draws such point-circles of randomly varying sizes, color, alpha and position. The idea for the demo is from the Gamedueno2 book The rendering code uses callbacks registered with the browser requestAnimationFrame API insead of a timer based rendering. Use the sliders to vary the maximum size of the circles and their total number and see the impact on the fps. The point size slider is clipped to the max point size obtained by querying ALIASED_POINT_SIZE_RANGE.

Max Size:
Count:
fps:


References

I2C Wrappers for the Arduino Wire Library

| Comments

Motivation

The current (v1.6.7) Arduino Wire library doesn’t seem to have a convinent API to read/write from/to I2C devices. All the pieces are available but what’s lacking is a wrapper around Wire that makes it straight forward to talk to I2C slaves. I wrote one similar to the PIC code I’ve used in the past, and it’s posted here.

Initialization

The Wire interface can be initialized by calling begin(). The default speed is 100kbps, which can be increased by calling SetClock().

1
2
  Wire.begin();
  Wire.setClock(400000L); // Set clock to 400kbps

Read

Reading from a slave typically consists of first sending the register ID you want to read out from followed by a repeated start condition [using endTransmission(false)]. Then you set the read bit and clock out the data [via requestFrom()].

1
2
3
4
5
6
7
8
9
10
11
12
void i2c_read(byte seven_bit_address, byte reg, byte* pData, byte len ) {
  byte i = 0;
  Wire.beginTransmission(seven_bit_address);
  Wire.write(reg);
  Wire.endTransmission(false);     // send a repreated start
  Wire.requestFrom(seven_bit_address, len, true); // read N bytes and send a stop bit
  while (Wire.available() && (i < len)) // Copy the already read out data into our buffer
  {
    *pData++ = Wire.read();
    i++;
  }
}

Write

Write is self explanatory.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void i2c_write(byte seven_bit_address, byte reg, byte* pData, byte len ) {

  Wire.beginTransmission(seven_bit_address);
  Wire.write(reg);
  for (int i = 0; i < len; i++) {
    Wire.write(*pData++);
  }
  Wire.endTransmission();     // send a stop
}

// An even simpler interface to write a byte
void i2c_write(byte seven_bit_address, byte reg, byte value ) {
  Wire.beginTransmission(seven_bit_address);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();     // send a stop
}

Example Usage

The code below shows how to read/write some data from/to the MAX30100 Pulse Oximetry sensor [I2C address = 0x57].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  Serial.begin(230400);
  // Initialize
  Wire.begin();
  Wire.setClock(400000L);

  // Do stuff..

  // Read
  byte id;
  i2c_read(0x57, 0xFF, &id, 1);         // Part ID register = 0xFF
  Serial.println("Part ID:");
  Serial.print(id, HEX);                // expected value is 0x11

  // Write
  byte data;
  data = (byte)0xA << 4 | (byte)0xB;    // Set the LED config register to 0xAB
  i2c_write(0x57, 0x09, &data, 1);      // LED config register = 0x09 
// OR i2c_write(0x57, 0x09, data);

  // Read back and check
  i2c_read(0x57, 0x09, &data, 1);
  Serial.println("LED Config = ");
  Serial.print(data, HEX);

Real-time 2D Plotting on Windows Using OpenGL

| Comments

Introduction - Why on earth?

There are plenty of plotting libraries for Windows using WPF / Win Forms like Oxyplot which can be configured to work with real time data. But rather than using yet another framework, I thought it would be a great idea to do some plotting of my own while also learning something about OpenGL and modern GPUs which I knew nothing about. This post is a result of that endeavour so please bear in mind that if you just want to draw a graph in a WPF application, you don’t really have to worry about OpenGL; it can be done quite easily with a Canvas element, or GDI if you are using Win Forms.

Now that all that’s clear, lets get into the lovely details.

Example Application

The example application plots real time data received from an accelerometer that’s mounted on an embedded device. The data is streamed to the PC via a Serial COM port which happens to actually be over Bluetooth. But any COM interface (USB-CDC / RS232..) will suffice. The accelerometer chip used is from ST Microelectronics - LIS3DH

A video of the application running on my PC is here:

The project includes a Simulation Mode which allows you to test the plotting without actually using a sensor, the plot just loops through some pre-recorded data. Just select the “Simulate” CheckBox and the “Start” button to start the simulation.

Download the example code here. Which you should be able to run immediately if you have Visual Studio 2012 or above.

(Modern) OpenGL in 10 minutes

I assume that like me you don’t know anything about OpenGL. If you do, then you wouldn’t be reading this anyway right? There are plenty of good tutorials on OpenGL written by those who know a lot more than me so I shall link to some that I found useful. You only need to know the absolute basics to be able to do a 2D plot, so once you reach the point where you can draw a Triangle, you know (one point) more than required and you can return back to this post. Most of the tutorials are in C++, but don’t worry about that just concentrate on understanding the principles.

  1. ArcSynthesis
  2. OglDev
  3. OpenGL Tutorial

Assuming that you have glanced through one or more of the tutorials above, I’ll briefly summarize the concepts relevant to the plotting scenario.

  1. OpenGL is basically a specification that lays out rules on how software can interact with a GPU chip (you can actually think of it as a GPU driver specification). It tries to strike a balance between being low level enough to be able to utilize all of the GPUs bells and whistles while being high level enough to be portable across different GPU chips. When GPU chip maker X releases a new chip, he/she makes sure that the drivers that they release for that chip contain APIs that are compatible with the latest OpenGL. specification. On Windows, drivers also comply with the Direct3D specification.

  2. The OpenGL interface specifies a lot of flags which encapsulate the State or Mode of the graphics engine. Typically you change whatever flags you need, then pass the vertices and other properties of the object you want to draw to the GPU and then issue the commands to draw the objects, that will be modified according to the current state (color, alpha etc).

  3. The GPU actually has a lot of little processors called Shaders that run at different stages of the drawing pipeline, and can run in parallel. OpenGL allows you to program these shaders via a C like language (GLSL). Generally you will create a separate shader program for each stage in the drawing pipeline. At minimum you need two shader programs - one for the Vertex shader (affects vertex properties) and another for the Fragment shader (affects pixel properties).

  4. Shader programs are compiled and linked somewhere during the run-time of your application, usually at initialization. You can switch the programs as and when you wish too. There are two kinds of variables that you can pass from your main application to a shader program
    • Attributes: These represent variables that is uniquely defined for every data point that’s input to that shader, for example every pixel in a fragment shader has a unique color/alpha value.
    • Uniform variables - These variables are constant for a particular draw call. Lets say you want to scale all the vertices by a factor of 2, you would store 2 in a uniform variable.
  5. The output of a Shader program is usually the setting of some pre-defined OpenGL variable (prefixed by gl ) or output some pre-defined value. For example the vertex shader program must minimally set the variable gl_Position for all vertices which denotes the position in space of each and every vertex that you draw. And the fragment shader must return the color for each pixel.

  6. The fundamental data structure in OpenGL is an Array (of float[]). These arrays store everything from Vertices to colors of pixels.

  7. Inside the application you will typically store vertices, colors etc inside Buffers/Buffer Objects. Usually you have one buffer in your main application for each attribute in the shader program. You can use an Array Object to encapsulate (bind) all the Buffer Objects related to a particular scene. So when you want to draw something you just have to bind the respective array object to the OpenGL driver and then ask it to draw the scene.

  8. When you want to draw stuff, you simply have to transfer all of these attribute buffers to the GPU and ask it to draw the image by telling the GPU the relationship between the buffers you sent and the attributes in it’s shader programs.

Wrappers for OpenGL on Windows

There are many wrappers that allow you to access the OpenGL API on Windows via C++ or C# like GLUT, GLFW, OpenTK, SharpGL etc. Except for GLUT, all of them can be used with C#/.NET. In this example I’m using SharpGL as it has built-in support for integrating OpenGL context within a WPF application. To use SharpGL just install the package with NuGet (Install-Package SharpGL.WPF) along with GlmNet which is useful for Math stuff. SharpGL also has Visual Studio project templates that you can use to create example projects.

Even though we use SharpGL for this example, as it’s basically just a thin wrapper over OpenGL it is easy to port the code to other frameworks like OpenTK.

Application Design

These are mainly 3 components to the application - the WPF User Interface that includes all the OpenGL plotting magic, a serial communication thread that collects data from the embedded board and a small module to interpret the data received from the accelerometer into X/Y/Z “points”. We shall look at each of these in turn

User Interface and Plotting

The UI consists of two areas - one occupied by the SharpGL control where we will do the plotting and another where we will have some simple buttons to ask the device to Start/Stop communication and a ComboBox to select the COM Port we want to communicate over. Data binding can be used to fill the combobox with the available serial ports by binding the contents with the GetPortNames method in System.IO.Ports :

1
2
<ObjectDataProvider ObjectType="{x:Type ports:SerialPort}" MethodName="GetPortNames" x:Key="portNames"/>
<ComboBox  ItemsSource="{Binding Source={StaticResource portNames}}" SelectedIndex="0"  x:Name="cmbxPorts" />

Since each data point from the accelerometer has 3 axes, the display surface available to the SharpGL control should be split into 3 regions. Also as far as OpenGL is concerned the entire 2D display region ranges from the X and Y values of [-1,1] so we need to convert every acceleration point into this range (normalization) before we push the data onto the VBO.

Vertex and Fragment Shaders

The Vertex Shader takes in two 3D vectors called vPosition and vColor for every buffer object and updates the variables gl_Position and color based on the information in vPosition and vColor. color is then passed on to the Fragment Shader which is used to generate the color for every pixel.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// The Vertex Shader 
// (1) takes in a 3D point and adds 'w' to it 
// (2) takes in a 3D color variable and adds Alpha to it and sets a custom variable called 'color'
#version 330

in vec3 vPosition;
in  vec3 vColor;
out vec4 color;

void main()
{

    gl_Position =  vec4(vPosition, 1.0);
    color = vec4( vColor, 1.0);
}


// The Fragment Shader outputs takes in color and outputs color

#version 330

in vec4 color;
out vec4 outputColor;

void main()
{
    outputColor = color;
}

Plotting Data

Plotting the background grid

Since the the grid is just 4 parallel lines that divide the screen into equal portions, it’s easy to draw first. This is done in the method void CreateAndDrawGrid(OpenGL GL) First of all we need to figure out the vertices to be drawn which just consists of 8 points to give 4 lines to split the figure into 3 equal regions. The points are - [(-1,-1), (1,-1)],[(-1,-1/3), (1,-1/3) …], done in the snippet

1
2
3
4
5
6
for (int i = 0; i < (C_NUM_Y_DIV + 1) * 2; i = i + 2)
{
    xgrid[i].x = -1f; xgrid[i + 1].x = 1f;
    xgrid[i].y = C_X_MARGIN_MIN + C_Y_STEP * i / 2; xgrid[i + 1].y = C_X_MARGIN_MIN + C_Y_STEP * i / 2;
    xgrid[i].z = 0f; xgrid[i + 1].z = 0f;
}

Next we need to set the colors or each of the vertices, which is set to White. If you select two different colors then the drawn line will be a color gradient between the colors.

Once the vertices and color buffers are set up, we just need to set up an Vertex Array Object (VAO) containing the two VBOs for vertices and colors, pass this VAO to OpenGL and ask it to draw a figure between these points. That’s what the rest of the code in the method does.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
////  Create the vertex array object.
vertexBufferArray = new VertexBufferArray();
vertexBufferArray.Create(GL);
vertexBufferArray.Bind(GL);

//  Create a vertex buffer for the vertex data.
var vertexDataBuffer = new VertexBuffer();
vertexDataBuffer.Create(GL);
vertexDataBuffer.Bind(GL);
vertexDataBuffer.SetData(GL, attribute_vpos, xgrid, false, 3);

//  Now do the same for the colour data.
var colourDataBuffer = new VertexBuffer();
colourDataBuffer.Create(GL);
colourDataBuffer.Bind(GL);
colourDataBuffer.SetData(GL, attribute_vcol, coldata, false, 3);

//  Bind the shader, set the matrices.
shaderProgram.Bind(GL);
shaderProgram.SetUniformMatrix4(GL, "modelview", mviewdata.to_array());

GL.DrawArrays(OpenGL.GL_LINES, 0, 8);

//  Unbind our vertex array and shader.
vertexBufferArray.Unbind(GL);
shaderProgram.Unbind(GL);

Plotting the raw data

Plotting the raw data is quite similar to what was done for the grid, only difference is that the vertices are created by mapping the accelerometer data into the [-1,1] space. The rest of the stuff - VAO / VBO is the same.

The method openGLControl_OpenGLDraw(object sender, OpenGLEventArgs args) is called automatically by the control, so every time control enters here we check if there is a new data point available to plot. If yes, that’s added to the VBO and the whole scene is redrawn. The two BOs used are: vec3[][] _data for vertices of the acceleration points and vec3[][] _dataColor that stores the colors for each vertex.

Rendering is done in the method void CreateAndPlotData(OpenGL GL, float[] raw_data, int figureID) which takes in the new data available and the subplot ID. It converts the points into the [-1,1] space and draws lines through them. Conversion is done by first normalizing the data into the range [-1/3,1/3] and then shifting the data by a fixed factor to align it into one of the subplots. i.e.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for (int i = 0; i < point.Length; i++)
{

    // 1. Normalize the point.x to range [-.33,.33] so we can fit in 3 figures in the range of [1,-1]
    _data[figNum][offset + i].y = 2 * (point[i] - Accelerometer.C_MIN_LSB) / (Accelerometer.C_MAX_LSB - Accelerometer.C_MIN_LSB) - 1; // [1,-1]

    _data[figNum][offset + i].y = _data[figNum][offset + i].y * C_Y_STEP / 2; // [-.33,.33]

    if (figNum == 0)
	_data[figNum][offset + i].y = _data[figNum][offset + i].y + C_Y_STEP + factor * C_Y_STEP;
    else if (figNum == 1)
	_data[figNum][offset + i].y += factor * C_Y_STEP;
    else if (figNum == 2)
	_data[figNum][offset + i].y = _data[figNum][offset + i].y - C_Y_STEP - factor * C_Y_STEP;
}

You can avoid having to reload some data by observing that in the BOs for the raw data, two things are fixed and can be loaded at start-up -

  1. The colors for each of the sub-plots are fixed (to Red/Green/Blue).

  2. The X and Z values of all the samples that will be shown on screen. The X values are limited by the total number of points we want to show on screen - C_SAMPLES_PER_FRAME

Serial Communication in Windows

The raw data comes over the COM Port and is received in the class called SerialPortAdapter. It runs a background thread that constantly tries to read bytes from the serial port using the SerialPort.Read() API. If you are running .NET 4.5 you can also read data asynchronously by accessing the SerialPort.BaseStream class, which is also shown in the example. Both methods worked fine for me.

Once one or more bytes are received, it’s pushed into a Circular Buffer and then the new bytes are passed to the Accelerometer class which can interpret the data received. The circular buffer in SerialPortAdapter discards bytes only if they have been successfully processed by Accelerometer. This is important because the Accelerometer actually needs at least 6 contiguous bytes to get a valid acceleration point.

Streaming can be started and stopped by sending a special character to the device.

Parsing Accelerometer Data

The Accelerometer class provides two important interfaces -

  1. Provides an API to interpret the byte stream received over the serial port. Converts these bytes into acceleration points and stores them in a Queue.

  2. Defines the Maximum and Minimum value of acceleration points possible. This allows the Drawing logic to scale the screen appropriately.

If you plan to use any other sensor, you just need to reimplement these things and everything else should scale automatically. The rest of the code could be split into another class called Sensor for a more modular design, if required.

For this example, the received stream consists of a continuous stream of acceleration points and an acceleration point contains 6 bytes, 2 bytes each per axis. The bytes are arranged in Little Endian format. So (X,Y,Z) of (0x0123,0x145,0x167) would be received as the stream: 0x23, 0x01,0x45,0x01,0x67,0x01

Final words

The code can be extended easily to use other sensors with other formats by modifying the parser and the constants in Accelerometer and some of the rendering code. You can also receive data from multiple serial ports by simply creating more instances of SerialPortAdapter and hooking them to the appropriate stream parser.

This example assumes that no bytes are lost in transmission, if a byte is lost then all the subsequent acceleration values could be misinterpreted. So to make the plotting robust to such failures, you would need to send data in frames and introduce headers, length bytes etc.

To make it convinent to use .NET colors and vec3[] arrays directly, I have added two Extension methods to the SharpGL DLL which are defined in SharpGLEx they define overloads for the OpenGL.Color() and VertexBuffer.SetData() methods.

References

  1. Official OpenGL Documentation
  2. Serial Ports On .NET
  3. Difference between Vertex Buffer Objects and Vertex Array Objects

Delegates in C#, Objective C and C - Exchanging Data Between Threads / Objects

| Comments

Introduction

A common problem in Object Oriented programming systems is how to pass data between Objects asynchronously. If your system is simple and procedural, communication is easy, the Parent Object can pass data to the Child Object as arguments and the Child returns the result. A simple method call will suffice. Things are not so straightforward if the objects are running asynchronously on separate threads and you want to pass data between them. Lets say you want to update your User Interface with the status of some task running in another object. This post looks at some of the ways to solve this problem in .NET C# and Objective C.

First we will look at asynchronous communication from the Child Object to the Parent Object, since this the most common use case. Data exchange from Parent to Child can usually be accomplished procedurally (via a method call on the Child Object) since generally you have a some UI Event or Parent Object Event which spawns the start of some background process.

Definitions and Example Scenario

Let’s think of the problem in terms of a Parent and Child object. By Parent Object I mean any object that instantiates another object called the Child Object. A good example of a Parent is the UI Object - an instance of UIViewController in Objective C or WindowsForm in .NET C#. A child object is any object that is instantiated in the ViewController or Form.

Let’s assume that the parent is a text box, and the child is a class that is communicating with a autonomous Robot. Let’s assume that the Robot sends us a message every 1 second about its whereabouts (over the internet or some other technology). We can easily simulate this Robot by having a periodic timer run in the Child class that spits out some data every 1s. I’ve chosen a timer for simplicity, it could very well be another thread. Our problem is how to display the information the Robot sends us on the UI (and have the user control the Robot).

Traditional Solution in C

If you were programming in C, this problem could be solved by using Callback methods. Callbacks are the standard pattern in event-driven Embedded Systems to pass data from lower layers into application layers. The UI file would define a method that would be called by the Child thread when it receives a message from the Robot. The disadvantage here is that we have ended up tightly coupling the UI with the Robot communication. If we change the UI and don’t want to display the message anymore, we’ll have to modify the Robot communication implementation to not trigger the callback anymore.

To make the implementation more flexible, you can use a higher level of indirection via function pointers. Instead of having a fixed callback function, define a callback function pointer or better yet a table of function pointers. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Callback functions receive a byte array pointer which points to the start of received data and length denotes the length of valid data in the array
#define C_MAX_RX_CALLBACKS  3u
typedef CALLBACKPTR (void)*(UINT8*rx_ptr, UINT8 length);
CALLBACKPTR RxCallBackArray[] = {CallBackMethod1, CallBackMethod2, CallBackMethod3 };

// Somewhere in RobotCommunication.c
if(Data_Received == TRUE){
    // Notify the application
    for(i=0;i<C_MAX_RX_CALLBACKS;i++)
        if(RxCallBackArray != NULL){
            (RxCallBackArray[i])(rx_data_ptr,length ); // Call the indexed function
        }
    }

}

The advantage here is that CallBackMethod1 could be deleted later on a UI change, and all you have to do is change the CallBackMethod1 entry to NULL. Also with an Array of callbacks, you can send the data to multiple application modules, say the UI module and a filtering module and so on.

Object Oriented Solution

The solution in Object Oriented languages is similar to that of C, in that it makes use of function (“method” to be more exact) pointers, but is much more powerful and easier to implement. At the heart of it is a thing called “Delegate”.

Delegates in C-Sharp

In C# a delegate is a build-in reference type, just like class, string and others. It specifically indicates a reference to a (surprise, surprise) method (or function in C). So it is nothing but a “Function Pointer Type” with some cool features that we will see soon. It can be used to declare any (static or instance) method - with any return value and any number of parameters.

Coming back to the Robot example, what we need to do is create a property with delegete type in the Robot Class. Parent classes that wish to be notified on the reception of a message, must assign specific methods to this property. In the Robot Class we just call all the methods assigned to this property when we receive some data that other classes may be interested in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// ------------- Class : Robot Communication --------------------
// 1. Declare the delegate to be implemented in the parent class
    public delegate void dataReceivedHandler(byte[] array);
    public dataReceivedHandler dataReceivedDelegate;
// ........	
// 2. Pass the received data to the delegate(s)
    if (dataReceivedDelegate != null)
    {
        byte[] data_to_send = {1,2,3,4};
        dataReceivedDelegate(data_to_send);
    }
// ------------- END --------------------
// ------------- Class : Parent (Form) --------------------
// 1. Assign the delegate to a specific method
	Robot = new RoboComm();
    Robot.dataReceivedDelegate += ProcessDataFromBot;
// 2. Process the data in the method
    private void ProcessDataFromBot(byte[] data)
    {
		// Do something with the data..
		
		// Since the delegate is called on the calee thread, UI updates can only be done using Invoke
        this.Invoke((MethodInvoker)delegate
        {
            listBox_Logger.Items.Add(DateTime.Now.ToString() + "Got some bytes");
        });
    }
// ------------- END --------------------

There’s a lot more you can do with delegates in C# - you can obviously assign and remove delegates at run-time, the methods assigned to a delegate may be static or an instance methods; if at the parent side you do not wish to go through the trouble of defining a method you can use an Anonymous Delegate - which is a lambda expression containing the code you want to execute in the delegate.

1
2
3
4
5
6
7
8
// Anonymous delegate version
Robot.dataReceivedDelegate += delegate(byte[] data){
    this.Invoke((MethodInvoker)delegate
    {
        listBox_Logger.Items.Add(DateTime.Now.ToString() + "And some Anon bytes");
        listBox_Logger.SelectedIndex = listBox_Logger.Items.Count - 1;
    });
};

If a delegate declaration specifies a return type and multiple methods are added to a delegate instance (multicast delegate), an invocation of the delegate instance returns the return value of the last method referenced. The return values of the other methods cannot be retrieved (unless explicitly stored somewhere in addition to being returned).

Delegates can be invoked from a class that did not declare the delegate. This may seem unnecessary but is important when you are inheriting a class from another, this allows the child class to trigger the delegate if required.

Events in C-Sharp

An Event is also a delegate, but it is restricted that it can only be called (triggered) from the class where it is declared, so inheriting subclasses cannot be trigger an event. You can work around this by declaring a protected method in the base class containing the trigger, that is invoked by the child class.

Also the .NET framework imposes some more restrictions on the delegate types that can be used as Events - they should “take two parameters, an “object source” parameter indicating the source of the event, and an “e” parameter that encapsulates any additional information about the event. The type of the “e” parameter should derive from the EventArgs class. For events that do not pass any additional information, the .NET Framework has already defined an appropriate delegate type: EventHandler.”

In other words it’s simpler to use events if you don’t have any data to pass, else just use delegates.

Synchronous and Asynchronous delegates

All the delegates we have seen so far are synchronous delegates. i.e. they are invoked synchronously by the callee object. The Robot object must wait for the execution of the delegates to finish before it can continue processing the next message. There may be situations where you want to do an asynchronous call on the delegates, C# has a couple of different ways for implementing this, some more equal than others. From .NET framework 4.0 and above you should use the Task Parallel Library (TPL) for such tasks. It provides a clean and feature rich interface quite similar in functionality to the Grand Central Dispatch (GCD) in Cocoa that we will see later. Using TPL APIs you can queue lambda functions or any delegates for execution at a later point of time. You can also easily receive a return value from this delegate.

The syntax to schedule a callback to be executed asynchronously on one of the system thread pools is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
byte[] test = { 1, 2, 3, 4 };
Task<bool> task = Task.Run(() =>
{
  // This is a delegate function
    return (asyncTplDataReceivedDelegate(test));
});

// This callback will execute once the task completes
// You can use some flags to set different continuations in case the task throws an exception and/or completes successfully
task.ContinueWith(_ =>
{
    // A lambda function that will be called automatically when the task finishes execution
    Console.WriteLine(" The result in TPL callback is: {0}.", task.Result);
});

// At any point, accessing the task.Result property causes the execution to block until the task is complete and the result is available.

If for some reason you cannot use TPL, then you can use BeginInvoke to achieve the same result; except that it’s a very ugly and messy way of going about it. Once upon a time, it was the only option though so I’ve described next it since I had gone thtough the trouble of figuring it out. Please skip it if you can :)

(Optional) Asynhronous delegates using BeginInvoke (Obsolete, use TPL if you can)

the BeginInvoke method (defined in the CLR for each delegate type) is used for this. Note that this is only applicable for delegates that have only one assigned target method.

When calling BeginInvoke on the delegate, you pass the delegate parameters + two additional parameters. One of them is a callback method which - if it exists - will be executed after the asynchronous method executes. The second is state information that can be passed to the callback, it can be any object. Once a BeginInvoke call is executed, the delegate will be executed on a new thread from the thread pool. BeginInvoke will also return an object implementing the IAsyncResult interface which contains information about the current state of the execution of the delegate method. Then the code execution continues.

How do you know that the delegate has completed execution? You have to use EndInvoke on the delegate. For every BeginInvoke there must be a corresponding EndInvoke. You have to pass the IAsyncResult object returned by BeginInvoke to it and any other ref or out parameters you expect to get back from the asynchronous delegate. Note that the call to EndInvoke is blocking, and only returns when the async operation has ended or an exception is generated.

This gives you 3 ways to get the result from the asynchronous call -

  • Wait-till-done Just call the EndInvoke once you have completed doing your tasks, and wait till the async operation completes.
1
2
3
4
5
6
  byte[] test = { 1, 2, 3, 4 };
  // Wait - till - done pattern
  IAsyncResult iar = asyncDataProcessDelegate.BeginInvoke(test, null, null); // Start async
  Console.WriteLine("Doing stuff");
  bool result = asyncDataProcessDelegate.EndInvoke(iar); // Wait for end and get result
  Console.WriteLine("After EndInvoke: {0}", result);
  • Polling method Poll the property AsyncResult.IsCompleted to know if the async operation has completed or not.
1
2
3
4
5
6
  IAsyncResult iar = asyncDataProcessDelegate.BeginInvoke(test, null, null); // Start async
  while (!iar.IsCompleted)
  {
      Console.WriteLine("Doing stuff");
  }
  bool result = asyncDataProcessDelegate.EndInvoke(iar); // get result and cleanup
  • Callback method This presents the cleanest Async pattern in that there is no waiting involved - you pass a callback to be invoked when the Async operation completes, and call EndInvoke from within this callback. You can also pass an arbitrary object to the callback method via the state parameter. The callback must be of type AsyncCallback.
1
2
// Option 2 - use a callback, no waiting!!
IAsyncResult iar2 = asyncDataProcessDelegate.BeginInvoke(test, new AsyncCallback(DelegateExOverCb), null);

(Optional) Redesign using Task based Asynchronous Pattern (TAP)

The use of TPL and async/await keyword suggests a redesign of the system based on the Task Based Asynchronous Pattern. What it means that instead of thinking in terms of callbacks, you can actually write your code as if you were dealing with a synchronous system while still not stalling any of the tasks. So you can write the code as if you were polling the Robot for any new data while not starving the parent object. Note that this is only supported from .NET 4.5, and therefore cannot run on a Windows XP system.

For example you could write something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// On the main form
bool _isCancelled = false;
async private void button1_Click(object sender, EventArgs e)
{
    while (!_isCancelled)
    {
	// Get new data
	byte[] data = await Robot.ReadBytesFromRobotAsync();
	// Update the UI
	Console.WriteLine("Got data from Robot: " + ByteArrayToString(data));
	listBox_Logger_TAP.Items.Add(DateTime.Now.ToString() + " " + ByteArrayToString(data));
	listBox_Logger_TAP.SelectedIndex = listBox_Logger_TAP.Items.Count - 1;
    }
}

// Inside the RobotComm class
async public Task<byte[]> ReadBytesFromRobotAsync()
    {
  TaskCompletionSource<byte[]> dataRxTcs = new TaskCompletionSource<byte[]>();
  Console.WriteLine("Awaiting begins ...");
  await Task.Delay(C_COMM_INTERVAL).ContinueWith(_ => { dataRxTcs.SetResult(new byte[] { 3, 4, 5, 6, 7 }); });
  Console.WriteLine("Awaiting ends ...");
  return dataRxTcs.Task.Result;
    }

Note how the design is simplified as we don’t have to keep track of any delegate pointers and the flow of the program is very obvious. In practice of course, everything after the await keyword will be executed asynchronously just as if it were a delegate.

Example Project for C

A Visual Studio project illustrating the above concepts simulating the Robot is here It includes code illustrating all of the above approaches.

Delegates in Objective - C

Objective-C uses delegates extensively to implement the callback pattern, just as C#. However there are some differences in the implementation and some more bells and whistles. So in Objective-C a delegate is NOT a function pointer; but rather an object pointer that points to the object that implements the callback (delegate) methods. Obj-C defines a keyword called protocol which can be used to declare the callback functions that a delegate to a class must implement. By default these functions are mandatory, meaning that all objects that want to be a delegate of a particular class must implement all the callback functions that the class expects. Optional functions must be declared using the optional keyword.

For our example, we have a View Controller class that is the parent and wishes to be the delegate of the RobotSim class. RobotSim class will call the View Controller’s implementation of the protocol.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  // RobotSim.h
  // In RobotSim declare the “protocol”. Any delegate of RobotSim must implement all the callbacks declared here (unless they are optional). 
  @protocol RobotCommDelegate
  // Required APIs go here:

  - (void) handleRxedDataSync: (NSArray*)array; // We'll encapsulate the received data in an NSArray for simplicity. This is not the most efficient idea.

  @optional
  // Optional APIs go here:
  @end

  // Now we need a property to hold the pointer to our delegate
  @interface RobotSim : NSObject

  // A property to hold the pointer to my delegate
  @property (nonatomic, weak) id <RobotCommDelegate> delegate;

  @end

  // RobotSim.m
  // In response to some event, trigger the delegate
  if ([delegate respondsToSelector:@selector(newFrameReceived)]) {
  [delegate handleRxedDataSync:data];
  }


  // ViewController.h
  // Tell the compiler that VC wants to be a delegate of RobotSim by using the <> brackets
  #import "RobotSim.h"

  @interface ViewController : UIViewController <RobotCommDelegate>

  @property (nonatomic, strong) RobotSim myRobot;

  @end

  // ViewController.m
  // Assign the delegate pointer
  myRobot.delegate = self;

  // Implement the callback which is part of the protocol
  - (void) handleRxedDataSync: (NSArray*)array
  {

  // blah blah blah
  }

That’s all there is to it. An interesting corollary of the delegate being an object pointer is that, the delegate class can cheat and call any function defined in the parent class if required (even if it’s not part of the protocol), and can also use this reference to access public properties of the parent class.

So this is an example of a “Synchronous delegate”. The callback will execute in the delegate object’s context, and it’s a blocking call as far as the delegate thread is concerned.

Asynchronous delegates using the Grand Central Dispatch (GCD)

Apple has made it really easy to live asynchronously with the GCD. To execute a function asynchronously, all you need to do is to pass it as a block to a GCD queue, and the framework takes care of almost everything else. If you want to be notified when the function has finished executing, there’s a GCD API for that too. Though there’s a lot to be said about GCD, we will just concentrate on what necessary to implement Asynchronous callbacks.

Steps to execute an asynchronous method are:

  • Make a Queue At some point in your application create a separate queue for the method to run, so that you don’t block the main thread. Or you can use one of the “Global Queues” via dispatch_get_global_queue(). Creating a custom queue is good if you want to run code you push onto it serially, FIFO order (not LIFO). If you use one of the global queues, then code runs concurrently and there is no guarantee that the block you pushed onto it first will execute first. The main (UI) queue can be accessed by calling dispatch_get_main_queue(), but you are generally better off not using it.

  • Pass the method to the Queue To execute the callback asynchronously, just use dispatch_async(), and pass it the Queue and Callback you want to execute.

1
2
3
4
5
6
7
8
9
10
11
      dispatch_queue_t myQ;
      myQ = dispatch_queue_create("com.example.myQ", NULL);

      // callback
      dispatch_async(myQ, ^{

      if ([delegate respondsToSelector:@selector(newFrameReceived)]) {
	  [delegate handleRxedDataSync:data];
      }

      });
  • Call the completion handler If you want to be notified asynchronously of when the delegate has finished processing the data, then you simply have to call the completion block after you executed the call on the delegate. it’s better to use the global queue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
      dispatch_queue_t myQ;
      myQ = dispatch_queue_create("com.example.myQ", NULL);

      // callback
      dispatch_async(myQ, ^{

      dispatch_retain(myQ);

      if ([delegate respondsToSelector:@selector(newFrameReceived)]) {
	  [delegate handleRxedDataSync:data];
      }

      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ [self completionHandler];}); // Delegate has completed its work!

      dispatch_release(myQ);

      });

And that’s all there’s to it!!

A minor note: if your delegate happens to be running on the main thread, AND you only have one parameter to pass via the delegate AND it does not return anything; then a simpler alternative without using GCD is to call performSelectorOnMainThread:

Delegate pointers and ARC / Garbage Collection

In the Objective-C example above, you might have noticed that the delegate property was declared as a weak reference. This is important as the Automatic Reference Counting scheme of memory management employed by Objective-C cannot figure out circular references. What has happened here is that the ViewController object holds a reference to RobotSim via the property myRobot, and myRobot in-turn holds a reference to ViewController via it’s delegate property, thus setting ViewControllers retain count to 2. So when you or the system tries to deallocate the ViewController object, it won’t work because it’s reference count is non-zero (1). If you declare the delegate as a weak reference, then the compiler will take care that the ViewControllers retain count will not be incremented when you do myRobot.delegate = self;.

For C#, since the CLR does not use ARC but something called mark and sweep garbage collection which is able to release circular references, so you don’t need to do anything special.

Example Objective C Project

Since the iPhone comes built-in with a lot of nice sensors, we will use this data to replace the hypothetical Robot. To Illustrate delegates, I’ve chosen to read the accelerometer + magnetometer + gyro data available from the Core Motion framework. And to demonstrate Asynchronous delegates, I’ve chosen to read data from the GPS via the Core Location framework. There’s a class called RobotSim which reads the accelerometer, gyro and magnetometer data every 0.5s via a timer. This data is passed on to the ViewController using a synchronous delegate. The GPS location data is posted asynchronously using the Grand Central Dispatch methods described above. The project can be downloaded here.

References:

  1. Asynchronous patterns
  2. Events in C#
  3. Blocks in Objective-C
  4. GCD Docs
  5. Mark and Sweep GC
  6. ARC and Circular reference
  7. Apple official doc on ARC and Retain cycles

Adding Bluetooth to Your Embedded Device

| Comments

Introduction

So you are tired of using USB cables or even USB – UART converters and want to have some wireless action on your device. You think bluetooth might be the best option but are confused by all the layers on the stack and the various versions like BT2.0, BT4.0, BLE and so on. This post will try to shed some light on this and summarize the options available and how difficult or easy it can be to add BT to your device.

Intro to BT versions

At the moment the main BT versions common are BT 2.0, 2.1, 3.0 (High Speed) and 4.0 (latest version). Most Host devices at the moment support BT2.1 while newer devices like iPhone 4S have BT4.0. The range of a BT device depends on the “Class”, Class 1 being the maximum range and Class 3 the lowest. For indoor applications, with a range of 10m or less, Class 2 is the answer.

Now you can think of BT4.0 as being the sum of BT 2.0/2.1/3.0 (called “Classic Bluetooth”) and Bluetooth Low Energy (BLE). And the cool thing of BLE is that it is an entireley new and simpler protocol from the ground up, including the physical layer. It specifically targets applications where you don’t need to stream a lot of data, but you just want to send some small data periorically or so. The problem with BLE right now is that most Phones/PCs do not support it yet.

Another thing worthy of mention in the Classic BT vs BLE debate is that if you want to have a device that can talk to iPhone/iPad/iPod, then it is better to use BLE because you do not have to sign up for the Made For iPhone program to use BLE

BT Soc vs Module …BT2.0

Whatever BT version you want to add to your device, you have basically two options – use a BT SOC chip from Ti, CSR or someone else OR use a BT “module” from Roving Networks, Panasonic or someone else. The difference is that the SOC is just the chip with the RF front end and implementing the BT stack up to the HCI interface, while the module will come with an antenna and the entire BT stack up to some “Profile”, usually the Serial Port Profile (SPP). SPP is what we need to transmit data bytes between BT devices.

SOC

The SOC is cheap (1-3$) but it’s only the chip – so it is your responsibility to design the antenna, get the BT certifications and in the case of BT 2.0 – 3.0 write a significant amount of software (the BT stack from the HCI layer upwards to RFCOMM/SPP) before you can transmit a byte of data from your favourite mobile phone to your device. In other words, using BT 2.0 – 3.0 on your device by adding an SOC is not for the weak of heart.

If you do decide to go the SOC way, I have found an open source stack that actually works - I have tested it - on PIC32. You should check it out. It is entirely event based and build upon the existing Microchip USB drivers. The whole stack compiles into less than about 8KB ROM, though it does require a heap around 4kB.

Modules

The simpler option is to buy a ~15$ module from Roving Networks or Panasoic or someone else. These modules have the entire stack up to SPP built-in and also remove the burden of certification from you. All you have to do is plug in the module to your PCB and configure it with your MCU by sending some AT commands over the UART. You can almost immediately start working on your Application as if it were a serial port.

BT Soc vs Module …BLE

The SOC vs Module question plagues BLE too. But in this case the burden of implementing the stack is no longer upon you as the BLE stack is much simpler than Classic BT. Even the SOC chips come with a built-in stack but some of try to trip you by forcing you to buy IAR compilers and other usless stuff. All this is documented extensively here.

If you decide to use a module for BLE, then you would want to look at Murata or Bluegiga.

In the next posts I will post some of the code I have been using to talk to my Roving Networks BT2.0 enabled device from Windows, Linux and Android.

Integrating Chan’s FatFs Library With Microchip Applications Library’s USB Stack

| Comments

Introduction

The Microchip Applications Library has a lot of great code that is easy to integrate and can bump up the feature set of your product in hours. So far I have had the opportunity to use some of the USB (MSD,HID,MS-Host) stacks along with their FAT library (FSIO). The USB stacks, along with their well written application notes are very good and quite easy to integrate, even if you know nothing about USB. Hovever, their FAT library is not the best out there. It takes up quite a lot of code + data space, is slower than Evolution (when there’s no external duress) and not extensible – for instance to support multiple volumes or long file names.

FatFs can solve all these problems. It seems to the handiwork of a one samurai army, who has done a lot of other cool projects too. In spite of doing all this stuff that I would gladly sell off my left testicle for, he actually refers to himself as a “mediocre” embedded systems engineer!! Anyhow, it’s also released with a free, open source, do-whatever-crap-you-can-with-it license.

Groundwork

This post will explain how to integrate FatFs to a Pic24 project. Sample code is also available for download. Most of the information contained here is just an aggregation of the things I found trawling the posts on Microchip forums.

Before going into the details, the files involved and their function should be evident. This is summarised in the table below. Note that both FatFs and FSIO have separated the FAT layer from the lower disk access layer. So you can build the system on different types of memory, furthermore in the case of FatFs your application can manipulate multiple memory types simultaneously. In this example I will only consider SD cards (over SPI) and USB Mass storage devices. You should also download the latest FatFs library and the sample

Function MAL Files FatFs Files
FAT File System fsio.c/h + FS config files ff.c/h + ffconf.h
SD card access sd-spi.c/h diskio.c/h

1. Integrating FatFs (with an SD card access)

In this scenario, your PIC is interfaced to an SD/MMC card via SPI and you have to set up a FAT system to access data on the SD card. You should not have to change anything to the ff.c/h files. But you have to add a call to the timer function and implement a function to return the timestamp for the files. Then you have to modify the diskio.c routines to match your particular SPI port. There are a few sections in Chan’s code marked as “Platform Dependent” that you need to modify.

2. Integrating FatFs with the MAL USB Library

  • Your device is a USB Mass Storage Device Something that might not be apparent on first glance is that for the case of a USB MS-device, you DO NOT need to implement a FAT system on the Device. The USB Host will take care of implementing the file system and/or formatting the device. So all you have to do is plug the MAL USB MS-Device routines to your diskio.c/h routines (see usbdevFatFs.c/h in the example code).

  • Your device is a USB Mass Storage Host: In this scenario, your PIC is a USB Mass Storage Host and wants to read/write data on a USB Mass Storage Device like a thumb drive. Now in this case, your application does have to implement a FAT (or some other) file system on TOP of the USB layers in order to read / write the thumb drive. The difference between the case 2.b and 1. is that the diskio.c routines are different and they access the USB BUS and the SPI BUS respectively.

  • Finally, What if your PIC talks to an SD card, and also acts as both a USB Mass Storage Device and Mass Storage Host? This is a case when you can use the multiple volume support in the FatFs (one volume is the SD card and the other is the USB MSD thumb drive). All you have to do is pass the volume number to the FAT routines, and you have to modify diskio.c to call the appropriate low level routines based on the passed in drive volume number (see the diskio.c file in the example code). The example code is based on the USB Mass Storage host+device usecase, it’s tested and it works!

ExampleCode

PIC32 Drivers for ILI9486L and HX8347G TFT Controllers

| Comments

Introduction

This post builds upon the previous one, and expounds some of the details of the communication interface between the PIC32 Parallel Master Port module and LCD panel controllers – ILI9486L and HX8347G.

Implementation

Both the display controllers support the 16 bit Intel 8080 Mode with 16BPP. The Intel 8080 mode defines 4 control lines in addition to the 16 bit Data Bus and that is what I am using. The control lines are – RDS (Read Strobe, WRS (Write Strobe), Data/Command (D/C#) Select (also called Register Select). As is evident from the names, the Read and Write strobes are used to latch the data on the bus. So to Write data on the bus, the PMP loads data (D0 – D16) and then pulls the WRS line low, when the WRS is pulled High, the display controller latches the data on the bus. Similarly for a Read, the Host PMP pulls the RDS line Low, the controller outputs data on the bus and the host reads this data on the RDS Low to High transition. The D/C# line is used to indicate to the controller whether the master is sending a command or writing/reading data.

If you are using the PIC32′s PMP, the RDS and WRS strobes are generated automatically by the hardware when you Read and Write the PMP data register. Only the D/C# and CS lines need to be generated in the driver. Typical Write and Read operations with the PMP looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Delays execution for PMP cycle time.
#define PMPWaitBusy()   while(PMMODEbits.BUSY);

//Writes command.
void WriteCommand(cmd)
{
    CS_LAT_LCD = 0;
    DC_LAT_BIT = 0;  // To write data set this bit to 1       
    PMDIN1 = cmd; // Just writing data to PMDIN1 causes the WRS to be generated and data to be loaded on the bus        
    PMPWaitBusy();
    CS_LAT_LCD = 1;
}

UINT16 ReadData(cmd)
{
    CS_LAT_LCD = 0;
    DC_LAT_BIT = 1;
    ret = PMDIN1; // The first read gives you old data on the bus, need to do a second read to get the new data        
    PMPWaitBusy();
    ret = PMDIN1;
    PMPWaitBusy();
    CS_LAT_LCD = 1;
return (ret);
}

The next task is to write a pixel in the display controller GRAM. HX8342 defines the following table for writing pixel data in the 16 bit mode:

image

What this indicates is that the color depth is controlled by setting the register 0x17 to 3, 5 6 or 7. We use 65K so we set it at 0x05. The command 0x22 is the RAMWR command which should be followed with the 16BPP data. The pixel address is set by manipulating the Start Column and Start Page registers as mentioned in the introductory post. So PutPixel on HX8347 looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void PutPixel(short x, short y, UINT16 color)
{
CS_LAT_BIT = 0;
// 1. Adjust the start column and page registers
WriteCommand(0x02);
WriteParameter(((WORD_VAL) (WORD) x).v[1]);
WriteCommand(0x03);
WriteParameter(((WORD_VAL) (WORD) x).v[0]);
WriteCommand(0x06);
WriteParameter(((WORD_VAL) (WORD) y).v[1]);
WriteCommand(0x07);
WriteParameter(((WORD_VAL) (WORD) y).v[0]);

WriteCommand(0x22); // send the RAMRW command
WriteData(color);
CS_LAT_BIT = 1;
}

This can be extended to implement GetPixel and so on. In the case of IL9486 the SC/SP values are stored in one register, so you just need to send one command followed by the “parameters”. PutPixel looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void PutPixel(SHORT x, SHORT y, UINT16 color)
{

   // modify the StartPage and StartColumn values
    CS_LAT_BIT = 0; // select device
   // send command to modify sc and sp registers
    SetCommand(0x2A);
    // send data
    WriteParameter(((WORD_VAL) (WORD) x).v[1]);
    WriteParameter(((WORD_VAL) (WORD) x).v[0]);
    WriteParameter(((WORD_VAL) (WORD) y).v[1]);
    WriteParameter(((WORD_VAL) (WORD) y).v[0]);
    // Now update memory
    SetCommand(0x2C); // command for memory
    WriteData(color);
    CS_LAT_BIT = 1;
}

Finally, the display orientation depends on the setting of some bits usually denoted by MX, MY and MV. You should be able to see their significance from your controller datasheet..

Source code is here: HX8347G ILI9486L

A Quick and Dirty Real-time Digital (IIR/FIR) Filter Implementation

| Comments

Introduction

You have this Data Acquisition System that coughs out data in real time, and you want to add a digital filter that takes each filter sample, throws out the filtered output. That’s the task of this post.

Let’s say the digital data is over your computer’s serial port, and you have set up some Matlab code to plot it already, now we need to filter each sample before storing it for plotting.

First of all you need to decide what kind of filter you want to use – low pass/bandpass etc, butterworth/elliptic etc, the filters order, cutoff frequency etc. And depending on all that use the matlab functions like butter(), ellip() to get the coefficients of the filter you want to use. You could calculate the coefficients by any other method also. This post assumes that you already have the filter coefficients and you just need some simple code to implement the filter.

Now that you have the coefficients usually denoted by the vectors a and b for the denominator and numerator respectively, let’s look at the general form of an IIR filter

Make sure that in your coefficients, .

Use the following code to implement the above filter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[b_lp,a_lp] = butter(8,40/(Fs/2),'low');
global dbuffer ;
dbuffer = zeros(length(b_lp),1); % buffer for LPF
%....... Read the ADC value from the serialport...
% Pass it to the filter subfunction
filtered_value = NewFilter(b_lp, a_lp, value);
%..... Plot data....

% NewFilter subfunction
function [data] = NewFilter(b, a,value)
k = 1;
global dbuffer ;
while(k<length(b))
dbuffer(k) = dbuffer(k+1);
k=k+1;
end
dbuffer(length(b)) = 0;
k = 1;
while(k<(length(b)+1))
dbuffer(k) = dbuffer(k) + value * b(k);
k=k+1;
end

k = 1;
while(k<length(b))
dbuffer(k+1) = dbuffer(k+1) - dbuffer(1) * a(k+1);
k=k+1;
end

data = dbuffer(1);

That’s all to it! Now consider an FIR filter, this is easier because now we do not have the vector a , so just delete the Multiply and accumulate loop for the a terms in the above code.

A moving average filter can also be implemented in a similar fashion. The code looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function [data] = MavgFilter(value)
 
k = 1;
global Dbuffer ;
global N;
% 1. shift by one element (discard the left most element)
while(k<N)
Dbuffer(k) = Dbuffer(k+1);
k=k+1;
end
Dbuffer(N) = 0;

k = 1;
while(k<N+1)
Dbuffer(k) = Dbuffer(k) + value;
k=k+1;
end

data = Dbuffer(1)/N;

Obviously, the same code can be used in any other language like C, or C# if you want to do analysis using them. If this implementation does not seem to be obvious from the equation, it’s because this is a Direct-Form Transpose II implementation. An advantage with this is that you only need to use one buffer to store intermediate results. In the more-straightforward Direct-Form Transpose I implementation, you would need two buffers - one for the numerator terms and another for the denominator terms.