Rick Swift & Apple & Embedded I make things. Sometimes, I’ll talk about it here.

My Gorram Frakking Blog

Radio Link Test 2

I put the n920 slave in a box and left it with a co-worker on the fifth floor of my office building. I took my laptop and the master radio over to our other building, 5 km away, and set up on the sixth floor. My co-worker was on the balcony outside the building, and I was in a conference room inside.

After we powered up the radios, and after I dealt with my radio coming loose from its dev board, we established a link and I was able to send a few characters to the slave. It was set up with a loopback connector, so those bytes came right back.

A query of the master's receive signal strength returned -91 dBm.

Hopefully this weekend we can do a 20 km test.

Balloon Controller v1

I've been hard at work this week on the Balloon Controller. It's an ARM-based embedded system with a bunch of sensors, intended to be flown as a payload on a high-altitude balloon. I'm very nearly finished with the PCB layout, but I thought I'd post a picture of it anyway:

BalloonControllerPCB1

The board features:

  • MakingThings Make Controller
  • Microhard Corp n920 radio comm link
  • GPS
  • Compass
  • Digital altimeter, 10 - 1300 mBar
  • Internal and external temperature sensors (internal is on the altimeter, external is a thermistor)
  • SD Card
  • System battery voltage sensing
  • Two USB ports, one for downloading new code, the other with an FTDI to access the debug serial port
  • Wide supply voltage range, 9 - 28 V (we'll probably use an 11.1V LiPoly pack for R/C cars

This is just a prototype. The next version will feature an Atmel SAM3S MCU instead of the Make Controller, some GPIO, and more refinement. It might even have an image sensor interface and be able to downlink images in real-time. And they'll be available for purchase, although we'll look at alternatives for the communications link, because the n920 radios are fairly expensive.

Stay tuned for updates.

Snow Leopard Code Blocks

I've recently been developing a Mac OS X project in which I was able to utilize the new code blocks feature to write some asynchronous code. They are a very exciting development, and I hope the C standards body adopts them as an official part of the language. They are similar to D's delegates. A good introduction to blocks can be found in Apple's Blocks Programming Topics.

I won't explain what a block is here, other than to say it's like a function. For a very brief introduction to the syntax of blocks, see “Declaring and Using a Block.”

What I will do is show you how code blocks can simplify inter-thread communication. First I'll present a pre-code block approach to the problem, and then show how, by using code blocks, you can dramatically simplify the code.

Background

The project includes a little USB hardware device, with Mac OS X software to talk to it. I needed to implement a console-like UI, allowing the user to send bytes to the device, and see the bytes coming in from it (in this regard, the device behaves like a serial port). The idea is to simply append whatever bytes are sent by the device to an NSTextView. To do this, it would be nice if the driver (a user-land driver embedded in the app) would just call my window controller whenever there is data available from the device.

However, there is currently only a blocking read call implemented in the driver.[1] So, I need a separate thread to block on a read call, and when data becomes available, to send my window controller a message to handle it. Problem is, the window controller needs to then interact with NSTextView, which should only be done on the main thread. The traditional solution in a situation like this is to use -[performSelectorOnMainThread:].


Traditional Approach

The window controller mentioned above is really just the app delegate (it's currently a very simple app). The app delegate's declaration looks something like this. For simplicity's sake, I've left out a lot, but for our purposes, assume that the user presses a button which calls -[openTerminal:], which starts the balls rolling.

[cpp 1="CallbackReadOp;" 2="@class" 3="Device;" 4="@interface" 5="AppDelegate" 6=":" 7="NSObject" 8="<NSApplicationDelegate>" 9="{" 10="NSWindow*" 11="mWindow;" 12="NSTextView*" 13="mConsole;" 14="Device*" 15="mDevice;" 16="CallbackReadOp*" 17="mReadOp;" 18="}" 19="@property" 20="(retain)" 21="IBOutlet" 22="NSWindow*" 23="window;" 24="@property" 25="(retain)" 26="IBOutlet" 27="NSTextView*" 28="console;" 29="@property" 30="(retain)" 31="Device*" 32="device;" 33="-" 34="(IBAction)" 35="openTerminal:" 36="(id)" 37="inSender;" 38="@end" language="@class"][/cpp]
Pretty straightforward, right? We've got some references to the UI, a reference to our device, and the action to start the read-append operation.

The implementation looks like this:

[cpp 1=""AppDelegate.h"" 2="#import" 3=""CallbackReadOp.h"" 4="@interface" 5="AppDelegate()" 6="-" 7="(void)" 8="readData:" 9="(NSData*)" 10="inData;" 11="-" 12="(void)" 13="appendToConsole:" 14="(NSString*)" 15="inString;" 16="@end" 17="@implementation" 18="AppDelegate" 19="-" 20="(IBAction)" 21="openTerminal:" 22="(id)" 23="inSender" 24="{" 25="[self.device" 26="26="open"];" 27="//" 28="Create" 29="an" 30="operation" 31="to" 32="loop" 33="reading" 34="from" 35="the" 36="board," 37="//" 38="calling" 39="us" 40="back" 41="when" 42="there's" 43="data" 44="available…" mreadop="[[CallbackReadOp" 45="alloc]" 46="init];" 47="mReadOp.device" 48="=" 49="self.device;" 50="mReadOp.target" 51="=" 52="self;" 53="mReadOp.selector" 54="=" 55="@selector(readData:);" 56="[mOpQueue" 57="addOperation:" 58="mReadOp];" 59="}" 60="-" 61="(void)" 62="readData:" 63="(NSData*)" 64="inData" 65="{" 66="NSString*" s="[[NSString" 67="alloc]" 68="initWithData:" 69="data" 70="encoding:" 71="NSUTF8StringEncoding];" 72="if" 73="(s" 74="!=" 75="nil)" 76="{" 77="[self" 78="appendToConsole:" 79="s];" 80="}" 81="}" 82="#pragma" 83="mark" 84="-" 85="#pragma" 86="mark" 87="•" 88="Attributes" 89="@synthesize" window="mWindow;" 90="@synthesize" console="mConsole;" 91="@synthesize" device="mDevice;" 92="@end" language="#import"][/cpp]
But wait, there's more! We need to implement CallbackReadOp. Here's its declaration:

[cpp 1="Device;" 2="@class" 3="CallbackReadOp" 4=":" 5="NSOperation" 6="{" 7="Device*" 8="mDevice;" 9="NSObject*" 10="mTarget;" 11="SEL" 12="mSelector;" 13="}" 14="@property" 15="(retain)" 16="Device*" 17="device;" 18="@property" 19="(retain)" 20="NSObject*" 21="target;" 22="@property" 23="(assign)" 24="SEL" 25="selector;" 26="@property" 27="(assign)" 28="bool" 29="reading;" 30="@end" language="@class"][/cpp]
The implementation looks like this:

[cpp 1=""CallbackReadOp.h"" 2="@implementation" 3="CallbackReadOp" 4="-" 5="(void)" 6="main" 7="{" 8="while" 9="(self.reading)" 10="{" 11="uint8_t" 12="12="buf[512"];" 13="uint32_t" numbytes="[self.device" 14="read:" 15="buf" 16="length:" 17="512" 18="timeout:" 19="250];" 20="if" 21="(numBytes" 22=">" 23="0)" 24="{" 25="NSData*" data="[NSData" 26="dataWithBytes:" 27="buf" 28="length:" 29="numBytes];" 30="[self.target" 31="performSelectorOnMainThread:" 32="self.selector" 33="withObject:" 34="data" 35="waitUntilDone:" 36="true];" 37="}" 38="}" 39="}" 40="#pragma" 41="mark" 42="-" 43="#pragma" 44="mark" 45="•" 46="Attributes" 47="@synthesize" device="mDevice;" 48="@synthesize" target="mTarget;" 49="@synthesize" selector="mSelector;" 50="@synthesize" reading="mReading;" 51="@end" language="#import"][/cpp]
This should be fairly self-explanatory. When this custom NSOperation subclass is added to the NSOperationQueue in the app delegate's -[openTerminal:] method, its -[main] is invoked. It sits in a loop, waiting for data to be available, and sends the app delegate -[performSelectorOnMainThread:withObject:waitUntilDone:], passing the NSData object it creates for the app delegate to handle.[2] If the user closes the console, the app delegate can set the reading property to false, and the loop will exit.

-[appendConsole:] takes care of presenting the data to the user in the app's window. The details of that aren't relevant here, so I've left it out.

So, all of that wasn't too bad. But it requires two methods in the app delegate, and a custom subclass of NSOperation. Now let's see how it works when using code blocks.

With Code Blocks

With code blocks, we can get rid of the custom NSOperation subclass altogether, and get rid of one of the two methods in the app delegate. All we need is a new implementation of -[openTerminal:]:

[cpp 1="(IBAction)" 2="openTerminal:" 3="(id)" 4="inSender" 5="{" 6="[self.device" 7="7="open"];" 8="//" 9="Create" 10="an" 11="operation" 12="to" 13="loop" 14="reading" 15="from" 16="the" 17="board," 18="//" 19="appending" 20="to" 21="the" 22="console…" 23="NSBlockOperation*" op="[NSBlockOperation" 24="blockOperationWithBlock:" 25="^{" 26="NSAssert([NSOperationQueue" 27="currentQueue]" 28="!=" 29="[NSOperationQueue" 30="mainQueue]," 31=""We" 32="should" 33="be" 34="running" 35="on" 36="a" 37="different" 38="queue!");" 39="while" 40="(self.reading)" 41="{" 42="uint8_t" 43="buf[512];" 44="uint32_t" numbytes="[self.device" 45="read:" 46="buf" 47="length:" 48="512" 49="timeout:" 50="250];" 51="if" 52="(numBytes" 53=">" 54="0)" 55="{" 56="NSData*" data="[NSData" 57="dataWithBytes:" 58="buf" 59="length:" 60="numBytes];" 61="//" 62="We've" 63="got" 64="some" 65="data," 66="now" 67="append" 68="it" 69="to" 70="the" 71="output" 72="view…" 73="NSOperation*" callbackop="[NSBlockOperation" 74="blockOperationWithBlock:" 75="^{" 76="NSString*" s="[[NSString" 77="alloc]" 78="initWithData:" 79="data" 80="encoding:" 81="NSUTF8StringEncoding];" 82="if" 83="(s" 84="!=" 85="nil)" 86="{" 87="[self" 88="appendToConsole:" 89="s];" 90="}" 91="else" 92="{" 93="NSLog(@"Got" 94="%lu" 95="bytes," 96="but" 97="no" 98="valid" 99="UTF-8" 100="string"," 101="data.length);" 102="}" 103="}];" 104="[[NSOperationQueue" 105="mainQueue]" 106="addOperation:" 107="callbackOp];" 108="[callbackOp" 109="waitUntilFinished];" 110="}" 111="}" 112="}];" 113="[mOpQueue" 114="addOperation:" 115="op];" 116="}" language="-"][/cpp]
What's happening here? There are two (nested) anonymous code blocks, each delimited by ^{ and }. This notation is a shorthand for a block that takes no parameters and returns void.

The Outer Block

First, line 9 creates an NSBlockOperation, and provides a block definition inline (the definition ends on line 43). This block is essentially the same as the code in CallbackReadOp: It loops over a device read call, creating NSData objects every time it gets some data. (It also asserts, on line 11, that it is in fact executing on a thread that's not the main thread.)

Keep in mind that the code in this code block will not execute right now (that is, right after the call to +[NSBlockOperation blockOperationWithBlock:]). It is simply being defined, and a reference to it is passed as the sole parameter to +[NSBlockOperation blockOperationWithBlock:]. More on that later.

On line 17, the code block references self.device. This is where the beauty and power of blocks becomes apparent: code blocks have access to all the variables in scope at the place they are defined. In this case, the blocks are defined in the scope of the AppDelegate method -[openTerminal:]. So they can access anything “regular” code in -[openTerminal:] can access, even though it will actually execute on another thread, after -[openTerminal:] has exited!

Note: It's important to understand that this access isn't completely without restriction; you still have to take care to synchronize access to shared variables just like you would with conventional multithreaded code, and remember that the block will hold strong references to garbage-collected objects (see the “Garbage Collection” section below). But what you don't have to do is squirrel away references to things like we did above with the CallbackReadOp class.

For more details on the subtleties of variable access from within code blocks, see “Blocks and Variables”.

Now take a look at line 45. Here we take the NSBlockOperation object op that we just created, and add it to mOpQueue, an instance of NSOperationQueue that we created earlier in the application's execution. At this point, our code block is scheduled to execute on a different thread, and -[openTerminal:] exits.

Eventually, that new thread gets scheduled, and the outer block we just created executes.

The Inner Block

So we have an outer code block executing on a thread other than the main thread, looping over a read call and passing data back to the main thread. Let's take a look at how it actually accomplishes that second part.

In the traditional approach, CallbackReadOp calls -[performSelectorOnMainThread:withObject:waitUntilDone:], calling the app delegate's -[readData:] and passing it the NSData object it created as a result of the device read. -[readData:] converts that to a string and calls -[appendToConsole:] to display it.

While we could certainly do that in the outer code block above, we can get rid of the -[readData:] method altogether and just call -[appendToConsole:] directly. Remember, a code block has access to everything that was in scope at the place it was defined, even when executing later. The only thing here, though, is that we need to call -[appendToConsole:] on the main thread. So we just do what we did with the outer block, but this time schedule it to run on the main thread, via +[NSOperationQueue mainQueue].

Everything from line 26 to line 36 will execute on the main thread. The separate thread conducting the device read will block until the inner code block has completed execution, thanks to the call to -[waitUntilFinished].[3]

Improving the Code

There is at least one small improvement we can make to this code, and that is to move the creation of the NSAttributedString to the outer block. Doing so will push more work into the other thread, reducing the burden on the main thread an improving UI responsiveness (on multi-core machines, at least). In this case it's not likely to make a noticable difference, but it's important to think in these terms.

Without code blocks, making such a trivial change would be more burdensome, because you'd have to change code in two different classes, and change a method signature. With the code blocks we've structured here, it's mostly just rearranging a few lines:

[cpp 1="(IBAction)" 2="openTerminal:" 3="(id)" 4="inSender" 5="{" 6="[self.device" 7="7="open"];" 8="//" 9="Create" 10="an" 11="operation" 12="to" 13="loop" 14="reading" 15="from" 16="the" 17="board," 18="//" 19="appending" 20="to" 21="the" 22="console…" 23="NSBlockOperation*" op="[NSBlockOperation" 24="blockOperationWithBlock:" 25="^{" 26="NSAssert([NSOperationQueue" 27="currentQueue]" 28="!=" 29="[NSOperationQueue" 30="mainQueue]," 31=""We" 32="should" 33="be" 34="running" 35="on" 36="a" 37="different" 38="queue!");" 39="while" 40="(self.reading)" 41="{" 42="uint8_t" 43="buf[512];" 44="uint32_t" numbytes="[self.device" 45="read:" 46="buf" 47="length:" 48="512" 49="timeout:" 50="250];" 51="if" 52="(numBytes" 53=">" 54="0)" 55="{" 56="NSData*" data="[NSData" 57="dataWithBytes:" 58="buf" 59="length:" 60="numBytes];" 61="//" 62="Convert" 63="the" 64="data" 65="to" 66="a" 67="string…" 68="NSString*" s="[[NSString" 69="alloc]" 70="initWithData:" 71="data" 72="encoding:" 73="NSUTF8StringEncoding];" 74="if" 75="(s" 76="==" 77="nil)" 78="{" 79="NSLog(@"Got" 80="%lu" 81="bytes," 82="but" 83="no" 84="valid" 85="UTF-8" 86="string"," 87="data.length);" 88="continue;" 89="}" 90="//" 91="We've" 92="got" 93="some" 94="data," 95="now" 96="append" 97="it" 98="to" 99="the" 100="output" 101="view…" 102="NSOperation*" callbackop="[NSBlockOperation" 103="blockOperationWithBlock:" 104="^{" 105="[self" 106="appendToConsole:" 107="s];" 108="}];" 109="[[NSOperationQueue" 110="mainQueue]" 111="addOperation:" 112="callbackOp];" 113="[callbackOp" 114="waitUntilFinished];" 115="}" 116="}" 117="}];" 118="[mOpQueue" 119="addOperation:" 120="op];" 121="}" language="-"][/cpp]

Garbage Collection

As you may have surmised by looking at the code, this app is garbage collected. That is, the code doesn't use retain and release to manage objects. This can obscure the fact that code blocks strongly reference the objects “captured” by them.[4]

Here, the blocks explicitly reference self and self.device, which will cause both of those objects to persist for as long as the blocks persist. If you were to directly reference an ivar, that would implicitly reference self, so again, both would continue to live for the life of the block. In this case, the app delegate and the device are both objects that always exist longer than the span of a user's console session, so this is acceptable.

The outer block defined above can live for a very long time (for as long as the user has the console window open). Blocking operations within a block can also cause a block to live for an extended period of time. If you're not careful, this can cause the worker thread count to increase dramatically, a condition you almost always want to avoid.

Final Thoughts

Code blocks (and the NSOperation classes to support using them) provide a clean and concise way of writing asynchronous and multi-threaded code. For this app, we got rid of an entire class definition (the CallbackReadOp), and a method in the app delegate. We did have to add an atomically-access reading property to the app delegate (not shown). Much easier to write, and to understand (once you understand code blocks).

Most often you will write small, anonymous blocks of code like those above and pass them to other functions for execution. Being able to access the variables in scope at the point of definition makes it very easy to write complex code, just don't forget to synchronize access to shared variables.

For additional information, and if you have Apple Developer access, check out A Short Practical Guide to Blocks.

Acknowledgements

Special thanks to Joar Wingfors of Apple, Inc. for technical review and other suggestions.

Notes

[1]Yes, it's possible to implement an asynchronous read, but we'll ignore that for now to better illustrate the advantages of code blocks.

[2]Don't worry too much about this tight loop hurting performance. The nature of the hardware device is such that it blocks for a while when there's no data, so this loop isn't as tight as it appears.

[3]While not strictly necessary, it reduces CPU load a little, allowing more bytes to accumulate in the USB buffers before they're read again. If this were a higher-speed device, it might be necessary to read it as fast as possible, but that's not the case here.

[4]Thanks to Joar for the term “capture” to denote external variables referenced by a code block. I think it will prove useful in future discussions of code blocks.

How Not To Seek Employment

I just got this email from someone looking for work. This is reminiscent of "please send me the codes."

LinkedIn
naiteek sangani has indicated you are a Friend:
Hi Rick,
I am a recent graduate from Columbia University and am seeking FULL TIME employment in the field of Software Development. Kindly get in touch with me if you have anything in store for me.
Looking forward to hearing from you.
regards,
- naiteek sangani

I'm not sure of this person's culture, and what passes for initiative or standard practice, but here in the US (and I think it's fairly evident from my LinkedIn profile that I'm in the US), this kind of approach is guaranteed to make any potential employer avoid you like the plague.

No, I Don’t Want to Invest in Your Securities or Commodities

For the last several months, I've been subject to a dramatic increase in the number of cold calls from companies suggesting I invest in oil fields, precious metals, or some security or another. Lately, I've been receiving a call or two per day. I've decided to list the companies and phone numbers in this post, so I'll continually update it.

The number they're all calling has been listed in the Do Not Call Registry for years. Now, like typical pro-consumer legislation, the Do Not Call rules allow companies with "existing relationships" to continue to contact you, as well as some degree of their subsidiaries and partners. It also has very little teeth. I had hoped for $500 fines per incident (similar to unsolicited faxing), but it doesn't appear to be so.

So, back to the calls. They're generally native English speakers, cheerful and energetic. They almost always imply a pre-existing relationship, by saying they're following up on the information I requested before.

To be clear: I have never requested such information. I am hypersensitive to marketing efforts, and do all my research anonymously online. I never knowingly request information of this nature. I think it's a blatant lie, intended to confuse me, or cause me to doubt myself, and is an attempt to shield themselves from the law that allows contact in case of pre-existing relationships.

On to the calls. This list is by no means complete. I've received literally dozens of calls, many I ignore. Some wake me in the morning. If I'm patient enough, I'll get a name from the caller. I also don't trust the caller ID; it could easily be forged, I think.

When I called one back (to verify it was not a legitimate missed call), he answered as if he were not expecting a business call. A "hello," some confusion, and after I asked who this was, because I saw the call in my call log, he replied, "This is the after-hours answering service for US Oil Fields" (a company that has called me before, or with a name similar to one). This makes me think that these aren't even call centers, but individuals in their homes, making these calls.

Date Company Agent Caller ID Location Notes
2010-02-04 1629 PST Properties Coast to Coast Jeff Deese 818 373-6746 Northern LA, CA
2010-01-25 1423 PST International Images Denis Sheild 702 922-1300 Las Vegas, NV Claims we spoke six months ago about "amazing photographs." This time I made a point of getting his name and company name, and so he took that opportunity to describe what they do. Something about selling "great" art, images, photographs from around the world. This is different from all the others, in that he wasn't asking me to invest in precious metals or oil fields. But it's the same kind of call; the suggestion that we've had a conversation prior to this.
2010-01-25 1402 PST Atlantis Group Ron Lewist (sp?) 310 856-9700 Gardena, CA I answered this call, and heard the caller speaking to someone near him, saying something about "the fucking transfer." It took five or six "Hello?" inquiries form me before he started talkign to me: "From the way you answered, you don't remember me." "You've never called me before." "Really? I have here in my notes that we've spoken." "You're full of shit. You've never called me. You're one of a thousand companies that's calling me with the same schtick." Something about I'm gonna miss out, that something's happening. I tried to tell him to put me on the do not call list, and he kept on yapping, so I hung up.
2010-01-21 1459 PST Advantage Management 954 351-5459 FL Also told me to invest in precious metals.
2010-01-21 1144 PST American Precious Metals Anna Risesh 954 944-0965 FL This company has called me many times. I've requested to be put on their do not call list, only to get a call from the same area code an hour later.
2010-01-20 1514 PST 214 628-9435 TX Also told me to invest in precious metals.
2010-01-20 1407 PST US Oil Fields 213 281-9074 Los Angeles, CA When I called, a man said, "hello." When I asked who it was, after fumbling a bit, he said "This is the after-hours answering service for US Oil Fields." This call and the next came within seconds of each other.
2010-01-20 1407 PST Domestic Development Company 214 350-1340 TX
2010-01-20 Fusion TX Might be one of the other calls this day.
2010-01-20 1302 PST Unanswered 214 628-9435 TX
2010-01-19 1459 PST Unanswered 214 628-9435 TX
2010-01-19 1039 PST Unanswered 954 944-0139 FL
2010-01-18 1235 PST Unanswered 954 491-9764 FL
2010-01-15 0807 PST Unanswered 214 628-9435 TX
2010-01-14 1611 PST Unanswered 954 944-0966 FL
2010-01-13 1214 PST Templeton Financial Group 561 499-9889 FL
2010-01-12 1417 PST Unanswered 214 628-9435 TX
2010-01-11 1339 PST Unanswered 512 623-5784 Austin, TX
2010-01-11 1137 PST Unanswered 214 628-9435 TX
2010-01-06 1102 PST Rockwell 954 725-1599 FL Precious metals.
2009-12-30 0921 PST Unanswered 214 628-9435 TX
2009-12-28 1525 PST Unanswered 818 373-6756 Los Angeles, CA I got another call from 818 for restaurant franchise opportunities.

I've filed a complaint via the Do Not Call Registry, but they don't address individual complaints. I filed a complaint with the FTC, but they don't, either. I think the next step will be to contact my local representatives.

Update 2010-01-25: I called the FCC today, but unfortunately the people who handle these complaints were gone for the day. Supposedly they'll be calling me back.