Archive for the ‘software’ Category

Ubuntu Linux on Desktop PC

Tuesday, September 8th, 2009

I refurbished a couple of PCs for my family to use, and installed the latest Ubuntu Linux on them – Ubuntu 9.04 Jaunty.  I also updated my dual boot work computer with the latest Ubuntu – it was running Kubuntu and the latest Kubuntu is just foreign to me.

As is usually the case, adding additional packages is essential to getting the computer working right for me.

Add Codecs, Java, and other Customizations

The official way to do this is documented in the Ubuntu Wiki under CommonCustomizations. There is also a wiki page on EasyCodecInstallation. The official meta package is called “ubuntu-restricted-extras” and this installs:

  • MP3 playback and decoding
  • Sun Java runtime environment
  • Flash plugin
  • DVD playback
  • LAME (to create MP3 compressed audio files)
  • msttcorefonts (may be missing in kubuntu extras)
  • DeCSS script to download and install for DVD viewing

$ sudo apt-get install ubuntu-restricted-extras
$ sudo /usr/share/doc/libdvdread4/install-css.sh
$ sudo apt-get install msttcorefonts

Add the ability to compile, edit, and maintain code

Here are the compilers and their documents
$ sudo apt-get install build-essential subversion-tools gcc-4.2-doc glibc-doc manpages-dev
$ sudo apt-get install mingw32 mingw32-binutils mingw32-runtime
I need access to subversion and XSLT ChangeLog tools
$ sudo apt-get install subversion-tools
$ sudo apt-get install xsltproc
I install a couple of editors, useful for various things. Kate is already installed.
$ sudo apt-get install scite
$ sudo apt-get install vim-full
Useful tools for cleaning up code, converting comments and line endings, and code statistics:
$ sudo apt-get install splint
$ sudo apt-get install sloccount
$ sudo apt-get install indent
$ sudo apt-get install liwc
$ sudo apt-get install tofrodos

Add favorite online music source and music/video player VLC

$ sudo apt-get install streamtuner
$ sudo apt-get install vlc

Add the Adobe Flash Plugin and Sun Java JRE

A lot of websites use Flash or Java for their user interface, so it seems that they are essential.

$ sudo apt-get install adobe-flashplugin
$ sudo apt-get install sun-java6-jre

Get rid of annoying PC speaker beep

Using a console, remove the PC Speaker driver from the kernel:
$ sudo modprobe -r pcspkr
Create /etc/modprobe.d/blacklist-user.conf and add a line to keep the PC Speaker driver from automatically loading:

# Keep the annoying beep from occurring
# don't load the PC Speaker driver

blacklist pcspkr

SynapticsTouchpad

The laptop has a touchpad, which is really annoying when you also have a USB mouse attached, because the touchpad picks up thumps made by my big fingers and makes the mouse click somewhere that you didn’t want it to click.  Correcting this in Ubunut Jaunty is as easy as selecting System > Preferences > Mouse, under the Touchpad tab. Uncheck the Enable mouse clicks with touchpad check box.

AVR ISP mkII on Ubuntu Hardy

Tuesday, May 12th, 2009

BACnet Development Kit

I created a BACnet Development Kit, compiled the open source BACnet Protocol Stack hosted on SourceForge.net firmware using gcc-avr, and attempted to load the firmware onto the kit using an Atmel AVR ISP mkII USB programmer.  I connected the AVR ISP mkII to my Ubuntu Hardy Linux PC and attached the 2×3 ISP cable to the development kit board, and attempted to program using avrdude:

$ avrdude -c avrispmkII -p m644p -P usb -e -U flash:w:bacnet.hex
avrdude: usb_open(): cannot read serial number "error sending..."
avrdude: usb_open(): cannot read product name "error sending..."
avrdude: usbdev_open(): error setting configuration...
avrdude: usbdev_open(): did not find any USB device "usb"

Wow! That wasn’t nice.  A search on the Internet turned up some answers about how to fix the problem, and I modified my /etc/udev/avarice.rules file to look like this:

SUBSYSTEM!="usb_device", ACTION!="add", GOTO="avarice_end"

# Atmel Corp. JTAG ICE mkII
SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2103", MODE="660", GROUP="dialout"
# Atmel Corp. AVRISP mkII
SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2104", MODE="660", GROUP="dialout"
# Atmel Corp. Dragon
SYSFS{idVendor}=="03eb", SYSFS{idProduct}=="2107", MODE="660", GROUP="dialout"

LABEL="avarice_end"

I disconnected and reconnected my AVR ISP mkII, and tried again.  I still had the same results.  I checked that I was a member of the dialout group:

$ groups
skarg adm dialout cdrom floppy audio dip video plugdev users fuse lpadmin admin

I looked at the symbolic link in the /etc/udev/rules.d/ directory and also consumed the README file.  My file had the following name:

/etc/udev/rules.d/z60_avarice.rules

So I changed the filename:

$ sudo mv /etc/udev/rules.d/z60_avarice.rules /etc/udev/rules.d/60-avarice.rules

I unplugged the AVR ISP mkII, and plugged it in again.  I tried to run avrdude again:

avrdude -c avrispmkII   \
     -p m644p -P usb -e        \
     -U flash:w:bacnet.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e960a
avrdude: erasing chip
avrdude: reading input file "bacnet.hex"
avrdude: input file bacnet.hex auto detected as Intel Hex
avrdude: writing flash (57406 bytes):

Writing | ################################################## | 100% 6.31s

avrdude: 57406 bytes of flash written
avrdude: verifying flash memory against bacnet.hex:
avrdude: load data flash data from input file bacnet.hex:
avrdude: input file bacnet.hex auto detected as Intel Hex
avrdude: input file bacnet.hex contains 57406 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 5.41s

avrdude: verifying ...
avrdude: 57406 bytes of flash verified

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

The kit programmed successfully, and began operation.

Interrupt Safe Ring Buffer Library

Saturday, October 25th, 2008

Christoper looks through a circular tube

I created a ring buffer library for embedded systems in C some years ago and have been using it when I need to add a simple queue to my software.  I knew it worked correctly since I created unit tests to validate the code.  However, I noticed that it wasn’t interrupt safe since one of the consumer variables is shared by the producer (the count).  This library requires disabling interrupts when consuming.  Not what I wanted.

There are a number of difficulties when designing ring buffers, mostly dealing with efficiencies of code or data, or the struggle between consumers and producers.  My generic ringbuf library had used a single fill count, but the count had to be updated by the interrupt service routine (producer) and by the routine that retrieved the data (consumer).  I tried to use read and write offset indices, but that required that I always keep an element open since the you can’t tell if the ring is empty or full when the head and tail are the same.

Absolute indices appeared to be interrupt safe, although they require that the buffer length be a power of two.  That seemed to be flexible enough for most embedded work.  I modified and tested my ring buffer library using that method, but my ringbuf, which allowed for a fixed length element,  seemed to be overkill for what I was using it for – gathering bytes from a serial interrupt service routine.  Its API also had a slight flaw such that if the consumer retrieved the data (via Pop rather than just viewing the first element), the producer was free to put new data into the buffer, overwriting the data just retrieved.

I had started my ring buffer library as a simple character (one byte) FIFO – first in, first out.  So, I revisited that code, and modified it to use absolute indices.  A simple byte ring buffer, first in, first out.  Now I had interrupt safe code that would work in my serial interrupt service routine.

Why go to the trouble to make a library module to handle a ring buffer when slapping the following quick and dirty ring buffer code (from Stefan) into the serial module would have worked as well?

   #define N 128
   volatile unsigned int head, tail;
   volatile char buffer[N];
   unsigned int inuse() { return head - tail; }
   void put(char c) { if (inuse() != N) { buffer[head++%N] = c; } }
   void get(char* c) { if (inuse() != 0) { *c = buffer[tail++%N]; } }

Because I needed to know that it worked correctly, and I like reusable library modules.  Especially high quality reusable modules.  Especially high quality reusable modules that include unit tests to validate functionality.  Unit tests that also serve as guides for implementers.

The new module files are ringbuf.c and ringbuf.h for the ring buffer with fixed sized elements, and fifo.c and fifo.h for the ring buffer with byte sized elements. All my versions of the ring buffer and the unit testing framework can be found in the ringbuf.zip file.

Sharkfest ’08 Conference for Wireshark

Monday, April 7th, 2008

sharkfest logoI was invited to attend Sharkfest ’08, a conference for Wireshark users and developers, held March 31-April 2 at Foothill College in Los Altos Hills, California. I had a great time, and am so grateful that Gerald invited me to attend. I attended as a Wireshark developer since I actively maintain the BACnet dissector. I went to the conference with several goals in mind:

  1. Figure out how to do BACnet segmentation
  2. Figure out how to get BACnet MS/TP into libpcap/winpcap.
  3. Add a couple of BACnet dissector enhancements to Wireshark.
  4. Learn about using Wireshark for problem network analysis.

I attended Laura Chappell’s training sessions, and learned a whole lot about Network analysis and the love-hate relationship between TCP/IP SYN, ACK, and Keepalives (#4 completed). I also wrote some Wireshark code during the classes which I promply submitted (#3 completed). Loris came into the activity center and sat down with my son Joshua and me, and so we discussed how to integrate BACnet MS/TP RS485 from serial port into libpcap/winpcap (#2 completed). On the last day and the last session of the conference, I attended a session by Richard Sharpe about file sharing protocols and learned about Wireshark conversations (#1 completed).

Vint Cerf and Gerald CombsWe were treated to an inspiration talk on Tuesday morning by Vint Cerf. After the talk, I went to Laura’s session, and Joshua talked to Vint. Vint signed Joshua’s Half-Life player guide, had photos taken with Vint and Gerald, and the Wireshark crew gave Joshua some swag.

Gerald treated the developers to dinner on Tuesday night at Trader Vic’s. I drove to dinner with Joshua and Jaap Keuter, and learned about PBX systems and Jaap’s passion for skydiving. At dinner I sat next to Ulf Lamping and learned about yet another division of Siemens and about Ulf’s love for motorcycle riding. Guy Harrris and Mike sat across from me.  Joshua ate with Gerald’s wife and daughter, and John Bruno’s wife.

The Foothill College campus was beautiful and on Spring Break. The food was awesome and plentiful.  The people were great!  The Wireshark sessions were helpful.  Maybe I will get to attend next year.

Read the Fine Manual or Datasheet

Sunday, March 30th, 2008

I found a bug in my Atmel AVR ATmega168 port of the BACnet Stack at SourceForge. It was the result of having not read the AVR datasheet close enough. Here is what the datasheet said:

The Transmit Complete (TXCn) Flag bit is set one when the entire frame in the Transmit Shift egister has been shifted out and there are no new data currently present in the transmit buffer. The TXCn Flag bit is automatically cleared when a transmit complete interrupt is executed, or it can be cleared by writing a one to its bit location.

SAGE_Instruction_Counter.JPGI had initially written the code to clear the TXC0 flag by clearing it, rather than setting it. Since the code could not determine when the end of the transmission occurred, I had added a _delay_us() function from the AVR-GCC library. This is what the AVR-GCC manual says about that function:

In order for these functions to work as intended, compiler optimizations must be enabled, and the delay time must be an expression that is a known constant at compile-time. If these requirements are not met, the resulting delay will be much longer (and basically unpredictable), and applications that otherwise do not use floating-point calculations will experience severe code bloat by the floating-point library routines linked into the application.

ENIAC_tubes.jpgSevere code bloat indeed! I had used a non-constant (the Baud Rate) in the delay call, and that resulted in a 4k increase in code size. After fixing the Transmit Complete flag functionality, I was able to remove the _delay_us, and the code size dimimished by 4k. On this 16k device, that means alot!

Statistics for the BACnet Stack at SourceForge on the ATmega168 are as follows:

IAR Atmel AVR C/C++ Compiler V5.10A/W32
10 191 bytes of CODE memory (+ 36 range fill )
775 bytes of DATA memory (+ 24 absolute )

avr-gcc (GCC) 4.2.2 (WinAVR 20071221rc1)
Program: 12052 bytes (73.6% Full)
Data: 481 bytes (47.0% Full)

With all the extra code space, I went on to add more functionality to the demo. The BACnet capabilities include WhoIs, I-Am, ReadProperty, and WriteProperty support. The BACnet objects include a Device object, 10 Binary Value objects, and 10 Analog Value objects. An LED is controlled by Binary Value object instance 0. All required object properties can be retrieved using ReadProperty. The Present_Value property of the Analog Value and Binary Value objects can be written using WriteProperty. The Object_Identifier, Object_Name, Max_Info_Frames, Max_Master, and baud rate (property 9600) of the Device object can be written using WriteProperty.

After adding all that functionality, I learned the hard way about the C-Stack differences between the IAR AVR compiler and the GCC-AVR compiler. The IAR compiler uses a fixed CStack size. If it is not set correctly, the CStack can overflow and cause problems in your code.

Johnniac.jpgThe GCC compiler uses the RAM not allocated to variables and text for the C-Stack. That means that the data value reported by the avr-size program is only part of the picture. If the data value is 481 bytes, and the device has 1024 total, then 1024-481=543 bytes are used by the C-Stack. In other words, don’t be fooled by the “47% Full” printed by avr-size and think that you have extra RAM. You might be able to add some more functionality, but certainly leave some RAM (or alot in my case) for the C-Stack. The GCC-AVR has two intrinsic variables for tracking the C-Stack: _end and __stack. These can be used to paint the C-Stack prior to its usage, and monitor the C-Stack during runtime. I added this technique to the demo.

The final statistics on ATmega168 demo of the BACnet Stack at SourceForge:

IAR Atmel AVR C/C++ Compiler V5.10A/W32
12 732 bytes of CODE memory (+ 36 range fill )
955 bytes of DATA memory (+ 24 absolute ) (CStack=0×200)

avr-gcc (GCC) 4.2.2 (WinAVR 20071221rc1)
Program: 15790 bytes (96.4% Full)
Data: 414 bytes (40.4% Full) (CStack=0×262)

Note: The photos are ancient computer memory from The Computer History Museum in Mountain View, California.  I’m visiting the area for the Wireshark Sharkfest ’08.

C/C++ Compiler Macros

Tuesday, November 27th, 2007

cityscape_night.pngEvery once in awhile, I need a macro to work around a difference in a C compiler.

For example, not every compiler for the Win32 platform has implemented C99 integer and boolean types, so I have stdint.h and stdbool.h files. Fortunately, The Open Group maintains an online definition for stdint.h and stdbool.h so I don’t have to guess about what is supposed to go in there. C99 also defines some new keywords: restrict, inline, _Complex, _Imaginary, _Bool. Since _Bool is used by stdbool.h, it may or may not have been defined by the compiler. What I needed was a macro defined by the compiler that tells me which compiler it is so I can avoid compiler warnings.

Digging up the compiler macros on the internet can be challenging. However, there is a nice project at SourceForge to track Pre-defined C/C++ Compiler Macros.

That makes things a whole lot easier!

Using GCC for ARM7 or AVR

Monday, September 3rd, 2007

Inspired by Building Bare-Metal ARM Systems with GNU series of articles, I recently ported the BACnet MS/TP datalink layer to an Atmel AT91SAM7S-EK board – an ARM7 processor – using a GCC cross compiler for ARM.

I evaluated GNU Toolchain for ARM, GNU ARM, WinARM, and YAGARTO toolchains on the Windows platform. They all have their merits, but all have some slight differences too. I followed an excellent tutorial by James P. Lynch called Using Open Source Tools for AT91SAM7S Cross Development to get me up and running quickly. Jim used the YAGARTO project as his toolchain.

I used the YAGARTO toolchain and created my own Makefile. Makefiles are an interesting bit of programming that seems to be a lost art. Any of the cross compiler toolchain builds should work with the Makefile with a slight modification to the name of the compiler (one of the differences in each of the various GNU ARM cross compiler projects).

During my travels down the GCC road, I found the GCC-AVR and WinAVR for Atmel AVR series of microcontrollers. I searched for GCC for an 8051. I found the SDCC project – Small Device C Compiler – for Intel 8051, Maxim 80DS390, Zilog Z80 and the Motorola 68HC08. Both projects are also in the Ubuntu Linux repository.  I noticed that the Microchip PIC24 compiler C30 is based on GCC and the source code is available on their website.

Quiet Surroundings without Distractions

Monday, April 2nd, 2007

QCAD and DXF drawing of a pumpI found Technical Drawing, Fifth Edition, by Giesecke, Mitchell, Spencer, and Hill, at a local Goodwill store. It is a wonderful book for those who want to learn about drafting. It is also great for woodworkers since it contains a detailed chapter on Geometric Constructions. It is great for graphic artists as it describes how to construct a large number of geometric shapes. However, the gem that I found that relates to software engineering comes from the beginning of the book in Chapter 2, section 2.3:

2.3 Drafting at Home or School. If a draftsman is to turn out drawings rapidly and accurately, he must work in quiet surroundings without distractions. Technical drawing requires headwork, and the draftsman who is whistling, singing, talking, eating, or smoking, is probably “pushing the pencil” without much mental activity behind it.

Someone knew the secret in 1967, the date the book was published, of how to get headwork done. The same technique for reducing interruptions applies to software engineering. We could say:

If a software engineer is to produce software rapidly and accurately, he must work in quiet surroundings without distractions. Software engineering requires headwork, and the engineer who is whistling, singing, talking, eating, or smoking, is probably “pounding the keyboard” without much mental activity behind it.

I think Joel had this concept of quiet surroundings right when he designed the Bionic Office. Peopleware also came to this same conclusion.

Daylight savings time

Monday, March 12th, 2007

Nightstand and alarm clockIt’s that time of year again. Time to spring forward. Well, not exactly the same time as last year. The formula for daylight savings time changed for this year. That meant that I had to rewrite firmware that used daylight savings time. According to Wikipedia,

Beginning in 2007, DST will start on the second Sunday in March (March 11, 2007), and change back to standard time on the first Sunday in November (November 4, 2007). Under Section 110 of the Energy Policy Act of 2005, the U.S. Department of Energy is required to study the impact of the DST extension no later than nine months after the change takes effect. Congress has retained the right to revert to the DST schedule set in 1986 if it cannot be shown that there are significant energy savings from an extension of DST or if the extension may prove to be unpopular with the American public. One potential issue is that some northern regions on the western edge of time zones will for the first time since the 1974-75 “almost year round” DST experiment have sunrise times that occur after 8am.

In two of my controllers I use, the built in hardware clock of the PC/104 card automatically handles the daylight savings time change. I simply set a bit and it would automatically spring forward or fall back. Well, almost. One of the controllers used a realtime clock chip by Odin which didn’t come out of daylight savings time and got stuck at 1am on the last Sunday of October. Since I could no longer utilize the hardware clock, I had to handle the daylight savings time change in software. There were two cases that I needed to cover. The first case is handling the timer interrupt and springing forward one hour or falling back one hour. The timer interrupt code turned out to be much simpler than I first thought. It is a good thing to be simple in an interrupt. Here is part of the code:

  1. if (data.tm_year >= (2007-1900)) {    /* begin DST – Second Sunday in March */    /* ANSI is months since January */    if ((data.tm_mon == 2 /*March*/) &amp;&amp;        (data.tm_wday == 1 /*Sunday*/) &amp;&amp;        (data.tm_mday >= 8) &amp;&amp; /* second Sunday */        (data.tm_mday <= 14) &amp;&amp;        (data.tm_hour == 2) &amp;&amp; /* 2:00 am */        (data.tm_min == 0) &amp;&amp;        (data.tm_sec == 0)) {        /* do something here */         }}

The second case was to determine if the date and time was during daylight savings time or not. This is used when the date and time get set on the controller, and to display the daylight savings time status. The code is more complex than the interrupt routine. Here is part of the code:

  1. if (year >= 2007) {    /* simple bounds check */     if ((month >= 3) &amp;&amp; (month <= 11)) {        /* get the start date for DST – Second Sunday in March */         if (month == 3) {            for (i = 8; i <= MonthDays(month,year); i++) {                if (DayOfWeek(DaysSinceEpoch(year,month,i)) == SUNDAY) {                    if (day == i) {                        time_now = TO_SECONDS(hour,minute,second);                         time_dst = TO_SECONDS(3,0,0);                         if (time_now >= time_dst) {                            dst = true;                        }                    } else if (day > i) {                        dst = true;                    }                     break;                }            }        }    }}

Testing the Daylight Savings Time algorithm was fairly routine using Unit Testing:

  1. void testDaylightSavings(Test* pTest){  /* original DST */  ct_test(pTest, IsDaylightSavings(31,12,2003) == FALSE);  ct_test(pTest, IsDaylightSavings(26,10,2003) == FALSE);  ct_test(pTest, IsDaylightSavings(25,10,2003) == TRUE);  ct_test(pTest, IsDaylightSavings(10,7,2003) == TRUE);  ct_test(pTest, IsDaylightSavings(6,4,2003) == TRUE);  ct_test(pTest, IsDaylightSavings(1,4,2003) == FALSE);  ct_test(pTest, IsDaylightSavings(1,1,2003) == FALSE);  /* new for 2007 DST */  ct_test(pTest, IsDaylightSavings(1,1,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(3,3,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(7,3,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(8,3,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(9,3,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(10,3,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(11,3,2007) == TRUE);  ct_test(pTest, IsDaylightSavings(10,7,2007) == TRUE);  ct_test(pTest, IsDaylightSavings(3,11,2007) == TRUE);  ct_test(pTest, IsDaylightSavings(4,11,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(7,11,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(8,11,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(30,11,2007) == FALSE);  ct_test(pTest, IsDaylightSavings(31,12,2007) == FALSE);
  2.  
  3.   return;}

Hope you are getting used to waking up earlier!

Removing Airplane Window Haze

Monday, February 19th, 2007

I like to take photographs of the earth while traveling in airplanes. Usually the passenger windows have a bit of a haze to them. I use The GIMP to get rid of the haze. Tools->Color Tools->Levels.

gimp_adjust_color_levels.jpg

I normally only have to use the Auto button. Sometimes I have to change an individual channel. Sometimes I can set the Black Level or White Level by selecting objects in the photograph. Sometimes I just move the little triangles under the histogram. The left triangle should be just at the start of the left side of the histogram. The right triangle should just be at the end of the right side of the histogram. The middle triangle adjusts the gamma value.
IMG_3090.JPG Before Adjusting Levels

Image above before adjusting levels. Image below after auto adjusting levels.

IMG_3090.JPG After Adjusting Levels