Raspberry Pi at Work

For the past couple of weeks I've been bringing my Raspberry Pi to work with me each day in my bag. But my desktop PC only has one network socket which is already in use, so I've only been able to connect the Raspberry Pi to my laptop. To make things easier, I bought a USB Ethernet adaptor, so that I can use my Raspberry Pi in the office with ease, in fact I can use it on any PC with a free USB socket. Here it is in action:

That works OK, which is cool. You can see I'm still running the Pi from the battery - which is still on it's original charge. It's given me light use of the Raspberry Pi for over two weeks. But at some point a Raspberry Pi powered laptop will appear I expect...

For my part, I'd be happy if somebody made an integrated Raspberry Pi case-and-battery. Then you could just carry one box around and recharge it like a phone or a kindle. But there may not be a market for crazy people like me who carry their RasPi around with them.

Implementing Function Calls

I've been busy lately adding the concept of function calls to my H2D2 programming language. It hasn't been as hard as I thought, but there has been a reasonable amount of code to write. I have added the notion of scope as well, so that when a function returns, any local variables go out of scope and the H2D2 virtual machine can free the memory allocated to them. Currently, functions can return a value (although it's possible in H2D2 to return nothing from a function too) ... but I can't yet pass parameters to functions, that's on my TODO list, I'll work on that next.

So here is the current test program that I'm using to see if it all works:

test()
loop(s=48)
  print 10
  print 13
  print s
  print 32
  x=test()
repeat (s=s+1 if s<58)
print x
return

function test()
  loop (s=65)
    print s
  repeat (s=s+1 if s<91)
return 42

This program simply outputs some ASCII characters, the result comes out like this:

ABCDEFGHIJKLMNOPQRSTUVWXYZ
0 ABCDEFGHIJKLMNOPQRSTUVWXYZ
1 ABCDEFGHIJKLMNOPQRSTUVWXYZ
2 ABCDEFGHIJKLMNOPQRSTUVWXYZ
3 ABCDEFGHIJKLMNOPQRSTUVWXYZ
4 ABCDEFGHIJKLMNOPQRSTUVWXYZ
5 ABCDEFGHIJKLMNOPQRSTUVWXYZ
6 ABCDEFGHIJKLMNOPQRSTUVWXYZ
7 ABCDEFGHIJKLMNOPQRSTUVWXYZ
8 ABCDEFGHIJKLMNOPQRSTUVWXYZ
9 ABCDEFGHIJKLMNOPQRSTUVWXYZ*

Simple stuff, but it demonstrates calling the "test()" function like a statement (ignoring the return value) and also assigns its return value to a variable too. I have also done some work allowing this type of code to be written out as labelled bracket notation. Essentially I'm treating each function like a seperate program, starting with its own root node, and then each call to that function simply points to the correct root node. This is how the above program looks if I render the labelled bracket notation generated from the bytecode:

Currently, when I parse the source code, I simply scan for function definitions and emit the code for them and then go back to a 'bootstrap' node which is the programs entry point. The starting point of the source code is pointed to from the 'bootstrap' node. It seems to work fine, and it means that programs always execute from node zero (which I'm making sure is always the bootstrap node).

In other news, I compiled H2D2 as a Windows dll, and used Interoperability to call it from C#, this worked a treat and was extremely fast. With the dll version, any output that the H2D2 program creates is returned as a pointer to a string, so after the program has been run the C# code needs to make an additional call the dll and tell it to free the string containing the output. But, my mandelbrot test program runs in about 200ms this way, since it doesn't have to muck about with writing to the screen. Once the C# program has all the output it can write it in one go rather than a character at a time, which is much quicker.

Now that I have installed Visual Studio 2012 I might be able to hide H2D2 behind a websocket interface. This should allow for a 'chatty' interface to H2D2 where you can ask it to run programs and get the results returned. This is also on my TODO list :-)

Raspberry Pi gone mobile

I'm writing this blog entry using my new Raspberry Pi, it's the second one I've bought. Not much unusual about that, but I'm doing it in Costa Coffee in Cambridge:

It's good that you can get your hands on a Raspberry Pi much easier now. I ordered this one on Friday night, and it arrived Tuesday morning. So that's less than 2 working days, which is much better. I got this one from Cool Components and I got the red ModMyPi case from the same place too. So because I had a Raspberry Pi in a case, I decided to go out on the road with it, well why not?

To get power to the Pi I'm using an emergency phone charger, mine is a TeckNet iEP380 which I bought from Amazon. It's rated at 5000mAh and seems to power the Raspberry Pi very well (although I've got nothing connected to the USB ports of the Pi). It might struggle if I connected any devices but I'm using the Pi 'headless' with just an ethernet cable to connect to my laptop.

So... now I can sit here in Costa Coffee, sipping my Cortado whilst working on my Raspberry Pi. Excellent, it's a good way to spend an hour or so in the morning.

Lightweight Cooperative Multitasking in C

I found this MSDN article quite interesting, it was one of those things that I wanted to try out for myself, just to see what was going on. For some reason, I decided to port the example code shown in the article to C, so here is the result:

// A working C example of the code described in the article here:
// http://msdn.microsoft.com/en-us/magazine/jj553509.aspx

#include <stdio.h>

#define task_begin(name, parameter)      \
                                         \
char name(parameter)                     \
{                                        \
  char yield_ = 0;                       \
  switch (args->task_)                   \
  {                                      \
    case 0:

#define task_end                         \
                                         \
    }                                    \
    args->task_ = 0;                     \
    return 0;                            \
  }

#define task_wait_until(expression)      \
                                         \
  args->task_ = __LINE__; case __LINE__: \
  if (!(expression))                     \
  {                                      \
    return 1;                            \
  }

#define task_return()                    \
                                         \
  args->task_ = 0;                       \
  return 0;

#define task_wait_while(expression)      \
                                         \
  task_wait_until(!(expression))
#define task_wait_for(name, parameter)   \
                                         \
  task_wait_while(name(parameter))

#define task_yield_until(expression)     \
                                         \
  yield_ = 1;                            \
  args->task_ = __LINE__; case __LINE__: \
  if (yield_ || !(expression))           \
  {                                      \
    return 1;                            \
  }
#define task_yield()                     \
                                         \
  task_yield_until(1)

typedef struct input_args
{
  int *target;
  int task_;
} input_args;

typedef struct average_args
{
  int *source;
  int sum;
  int count;
  int average;
  int task_;
} average_args;

task_begin(input, input_args *args)
{
  for (;;)
  {
    printf("number: ");
    if (!scanf_s("%d", args->target))
    {
      task_return();
    }
    task_yield();
  }
}
task_end

task_begin(average, average_args *args)
{
  args->sum = 0;
  args->count = 0;
  args->average = 0;
  for (;;)
  {
    args->sum += *args->source;
    ++args->count;
    args->average = args->sum / args->count;
    task_yield();
  }
}
task_end

int main()
{
  int share = -1;
  average_args aa = { &share };
  input_args ia = { &share };

  while (input(&ia))
  {
    average(&aa);
    printf("sum=%d count=%d average=%d\n", aa.sum, aa.count, aa.average);
  }
  return 0;
}

I hope that I got it right ;-) I didn't spend very much time on it. But I thought that somebody else might find it interesting, or maybe I'd want to come back to it at some point. So I thought that I'd post it... just in case.