TK

18Jun/120

World’s oldest photography

World's first photography (1826)

I found a little gem; The world's oldest photography, taken by Nicéphore Niépce 186 years ago, in 1826.

Notice the light being cast from both sides, so you can see the buildings being lit from the left and from the right. This is due to the 8-hour exposure of this photo.

Nicéphore was clearly a clever guy. His other inventions included the Pyréolophore, which is probably the first internal combustion engine, invented 1807. That year it powered a boat upstream on the river Saone.

Sources: Nicéphore (wikipedia) and Pyréolophore (wikipedia)

4Jan/120

Introducing 500px

To the photographers out there...

I've been active on 500px.com lately. It's a really cool photo sharing site where people aim to upload their very best photos. Most galleries are small, which makes it more fun to browse through them.

Take a look at it, and check out my portfolio here: http://500px.com/torbjorn
(link opens in a new tab).

19Jun/110

MSP430 and the GNU Debugger (GDB)

Here's a short how-to on how to use the GNU Debugger (GDB) alongside the MSP430 development tools on OS X (Note that these steps will also work on Un*x).

Up until now I've been using mspdebug for everything, and I think it's time to wield the power of gdb.

Start mspdebug like this:

$ mspdebug rf2500 gdb

In another window, start GDB and connect to mspdebug on port 2000.


$ msp430-gdb
GNU gdb (GDB) 7.0.1
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
(gdb) target remote localhost:2000
[...]
(gdb) file test.elf
[...]
(gdb) load test.elf
Loading section .text, size 0x4e lma 0xf800
Loading section .vectors, size 0x20 lma 0xffe0
Start address 0xf800, load size 110
Transfer rate: 728 bytes/sec, 55 bytes/write.
(gdb)

Here are some commands of interest:

  • info registers
  • info breakpoints
  • break <function-name>
  • continue / cont
  • q  (quit)

Full GDB manual here: http://sourceware.org/gdb/current/onlinedocs/gdb/

Examples will follow in later articles, but for now we've simply shown the few steps required to get started with GDB. Have fun!

6Jun/110

Quicktip: UTF-8 in irssi within GNU screen

Here's a small tip to get UTF-8 to work properly in irssi running within GNU screen:

Add the following to ~/.screenrc

defutf8 on

Then start screen with the -U parameter, and start irssi.

/set term_charset utf-8
/set recode_autodetect_utf8 ON
/save

Also add the following to your ~/.bashrc, but it may not be required:

export LANG=en_US.UTF-8
export LC_CTYPE=en_US.UTF-8

UTF-8 encoding now works, it's as simple as that. (Note for reference, I've only tested this within Terminal.app on OS X).  Next time you re-attach to this screen, remember to do so with the -UrD parameter.

TedSki on #motorcycles (EFNet IRC) came up with this solution and told me about it. Here's after the first test:


[20:37] < sgtzx> let's give it another shot
[20:37] < TedSki> sgtzx: 華語
[20:37] < sgtzx> yes, works!
[20:37] < TedSki> there ya go
5Jun/110

Fun with a chip from Texas Instruments [part 2]

Last time we simply switched on two LEDs and let them shine forever (well, until someone pulled the power!).  I feel it's almost too trivial of an example, but on the other hand; getting past the initial challenges of using the GNU assembler/linker and explaining the basic concepts is essential.

Let's take it one tiny step further.  Let's light up those two LEDs one after the other, like a siren light.

To accomplish this, we'll be exploring interrupts and timers. The MSP chip has a Basic Clock Module that helps us to write embedded applications with extremely low power consumption. We'll be using the DCO (digitally controlled oscillator) clock source. Now, three clock signals are available from the Basic Clock Module, namely ACLK, MCLK and SMCLK. We'll be using the SMCLK; the sub-main clock!

The clockrate at which we will be sourcing the SMCLK from DCO is approx. 1MHz. Not exactly mind-boggingly fast, but keep in mind that MSP is a very power efficient microcontroller.

Note that if you wanted to use the MSP for something that requires good timing, then you'd add a crystal to the circuit. I don't have a crystal, but I see that the LaunchPad development kit supports soldering a crystal oscillator onto it (e.g. a 32 768 kHz watch crystal).

In configuring the Basic Clock Module, I just went for the default settings as specified in the MSP430 user manual, as seen below:

    clr.b   &DCOCTL                             ; set lowest DCOx and MODx settings
    bis.b   #DCO2+DCO1+DCO0, &DCOCTL            ; select max DCO Tap
    bis.b   #RSEL0+RSEL1+RSEL2, &BCSCTL1        ; select range 7

We'll be using Timer A which is an integral part of all the MSP chips. Some MSP-chips also have Timer B onboard, but I haven't played with that yet. For this simple and rather unsophisticated example, we'll just set a "highish" TACCR0 value. Doing so we achieve a slight delay between changing the LEDs lights. You'll see that I used 0xFFFF in the source code.

Let's source Timer A from SMCLK. We're going to be using TACTL, the control register for Timer A. It has a structure specified in the manuals, and as you can see we set it to 0x0210. Translated to binary that is 0000 0010 0001 0000. If you compare this to the structure of this control register, you'll see that we'll be sourcing from SMCLK (and not ACLK etc), and MC "Up-Mode". Up-mode simply means that we let the timer count up to the value in TACCR0, and then it resets back to zero.

We still need to trigger an interrupt so we can alternate the lights! For this we'll be setting TACCTL1, which is the capture/compare control register for Timer A. As you can see from the source code below, I'm setting it to 0x0F0. That's 0000 0000 0000 1111 in binary. Have a look at the MSP430 specs, and you'll see that we're setting the CCIFG, COV, OUT and CCI flags. From this setting, we'll make sure that our interrupt is raised when the timer has counted up to the value in TACCR0.

Check the interrupt vector table below and note that I've inserted "siren" as the entry for the Timer A interrupt. This means that for each time the counter reaches TACCR0, we'll be executing the code from the "siren" label.

Let's get to the source. Take the test.asm file from the previous example, clear it and paste the following:

.global main

; Constants/registers
.set    WDTCTL,     0x0120          ; watchdog control port
.set    WDTPW,      0x5A00          ; watchdog power
.set    WDTHOLD,    0x0080          ; watchdog hold
.set    P1DIR,      0x0022          ; direction of data bits on port P1
.set    P1SEL,      0x026
.set    P1OUT,      0x021
.set    TACCR1,     0x0174
.set    TACCR0,     0x0172
.set    TACTL,      0x0160          ; Timer A is 0x0160 to 0x017F
.set    TACCTL1,    0x0164          ; Capture/compare control register
.set    DCOCTL,     0x056           ; DCO control register
.set    BCSCTL1,    0x058           ; Oscillator control register #2

; Settings for Basic Clock Module
.set    RSEL0,      0x01            ; These bits select the frequency
.set    RSEL1,      0x02            ; range of the DCO
.set    RSEL2,      0x04
.set    DCO0,       0x20            ; These bits set the fundamental frequency
.set    DCO1,       0x40            ; of the DCO, within the range defined by the
.set    DCO2,       0x80            ; RSEL bits above.

.text
main:
    dint
    mov     #0x0280, r1             ; set stackpointer to top of RAM
    mov     #WDTPW+WDTHOLD, &WDTCTL ; stop watchdog

    ; let's configure the basic clock module
    clr.b   &DCOCTL                             ; set lowest DCOx and MODx settings
    bis.b   #DCO2+DCO1+DCO0, &DCOCTL            ; select max DCO Tap
    bis.b   #RSEL0+RSEL1+RSEL2, &BCSCTL1        ; select range 7

    ; we set red LED, keeping green LED cleared for now
    bis.b   #0x01, &P1DIR
    bic.b   #0x40, &P1DIR

    ; set P1.0 = TA0.1 (OUT1 is timer A's output)
    bis.b   #0x01, &P1SEL

    ; we need to set CCR0,
    ; in our case to the highest possible value (all bits set in 16-bit value)
    mov     #0xFFFF, &TACCR0

    ; we need to source timer A from SMCLK, up mode. We counts up to the value in CCR0,
    ; and then it resets to zero.
    mov     #0x0210, &TACTL

    ; Interrupt when timer has counted up to the value in CCR0 (see above)
    mov     #0x0f0, &TACCTL1

    ; enable interrupts and shut down cpu (LPM0 with interrupts enabled)
    eint
    bis     #0x0018, r2

siren:
    bic.b   #0x01, &TACCTL1     ; clear interrupt
    xor.b   #0x01, &P1DIR       ; toggle red
    xor.b   #0x40, &P1DIR       ; toggle green
    reti

__noint:
    reti

.section .vectors, "a" ; Set attribs CONTENTS, ALLOC, LOAD, READONLY, DATA
    .word __noint, __noint, __noint, __noint
    .word __noint, __noint, __noint, __noint
    .word siren,   __noint, __noint, __noint
    .word __noint, __noint, __noint, main

As you may have noticed, our interrupt vector table contains a lot of references to __noint. That's good code-practice. If another interrupt is raised (for whatever reason, e.g. due to a bug), then we'll make sure that we run "reti" (return from interrupt) immediately, to handle it cleanly. This can often help with debugging, as sometimes you'd want to do something before the reti, and set a breakpoint to catch it.

You'll also notice that we're setting the CPU into LPM0 mode, aka "low power mode 0", and it simply means that we are only running the SMCLK and ACLK clocks on our chip. We've basically switched off the CPU. That's one of the cool features of the MSP, i.e. that you can enable the CPU (MCLK) when you need it, and you can even increase the clock frequency as needed as well for those computationally intensive moments, only to lower it shortly after to save battery.

Lastly, here is a video of the demo. I do sincerely apologize for the horrible video quality. :-)

Compiling and deploying the app is the same procedure as before:

$ msp430-as -o test.o -mmsp430x2012 test.asm
$ msp430-ld -o test.elf -T test.map test.o
$ mspdebug rf2500 "prog test.elf"
[..snip snip..]
Programming...
Writing  82 bytes to f800...
Writing  32 bytes to ffe0...
$

30May/110

Fun with a chip from Texas Instruments [part 1]

I've found this really cool chip. It's from Texas Instruments and it's called the MSP430. It's got a 16-bit RISC CPU inside of it, capable of different power modes (including ultralow power, down to 0.7µA at 1MHz!). You can even power this thing off a couple of AA batteries. You can get a development kit called the Launchpad for a subsidized price of approx $5 USD.

I run OS X (the same applies if you run Linux) so I could not run the Windows-based IDE that comes with the MSP chip. That's fine, because in this case I prefer my command-line tools anyway. In fact, to learn as much as possible about this chip, I wanted to get down to the bare metal and code some assembly!

So what do we need? Well, we need an assembler, a linker and a device programmer tool. I'm going to be using the GNU assembler and linker, along with mspdebug. (Use the links mentioned to get started).

Secondly, we need the official specs and datasheets in order to learn as much as possible about the CPU. The most important one is the user manual, which I've uploaded here.

Now let's begin. We first need to tell the linker about the memory map for the executable that we are going to produce. Looking at the MSP's memory map, we can see that code memory begins at 0xF800 and we are given 2kB of this code space. The interrupt vector table begins at 0xFFE0, and is exactly 32 bytes. There are different MSP chips with slight differences, e.g. the G2031 only has 512 bytes of code memory. The best thing is to have a look at the datasheet for the chip you'll be using (look for "Memory Organization"). I'm using the MSPG2231 chip.

Let's call this file test.map:

MEMORY
{
        TEXT    : ORIGIN = 0xf800, LENGTH = 0x0800
        DATA    : ORIGIN = 0x1000, LENGTH = 0x0100
        VECTORS : ORIGIN = 0xffe0, LENGTH = 0x0020
}

SECTIONS
{
        .text : { *(.text) } > TEXT
        .data : { *(.data) } > DATA
        .vectors : { *(.section .vectors) } > VECTORS
        .bss : { *(.bss) }
}

With this map file we're basically telling the linker that when it produces the final ELF executable, the target device needs to put the code data on 0xF800 (2kB space available), the interrupt vectors on 0xFFE0 and so on. Don't worry about the .bss section and the .data section for now, as in our first example we won't be using them.

Now, let's proceed with our first test program! Call this file test.asm.

.global main

.set    WDTCTL,     0x0120          ; watchdog control port
.set    WDTPW,      0x5A00          ; watchdog power
.set    WDTHOLD,    0x0080          ; watchdog hold
.set    P1DIR,      0x0022          ; direction of data bits on port P1

.text
main:
    mov     #0x0280, r1             ; set stackpointer to top of RAM
    mov     #WDTPW+WDTHOLD, &WDTCTL ; stop watchdog
    bis.b   #0x41, &P1DIR           ; lights up red LED and also green LED

    jmp $+0                         ; we are done

.section .vectors, "a" ; Set attribs CONTENTS, ALLOC, LOAD, READONLY, DATA
    .word 0x00, 0x00, 0x00, 0x00
    .word 0x00, 0x00, 0x00, 0x00
    .word 0x00, 0x00, 0x00, 0x00
    .word 0x00, 0x00, 0x00, main

Note that with the GNU assembler, any section that is not .text, .data, .bss, and so on, has to be added with ".section" (or .sect), this is unlike other assemblers.

Let's start with the bottom section - the .vectors section - just to get it out of the way. As you may remember, the interrupt vector table is 32 bytes (it is in fact 64 bytes on my chip, but I don't need to worry about the additional 32 bytes right now). The only vector I need is the RESET vector, and you'll see that I've pointed the last word (2 bytes) to main's address! Without this, you won't get very far. Also note that the section has got the "a" attribute. This is just so that the linker will include the .vectors section in the ELF executable that we'll be producing.

Let's have a look at the main procedure. Setting the stack pointer (SP is the same as the R1 register) at the top of RAM is a part of the initialization. We also stop the watchdog, although this code would have worked without it. The "BIS" instruction sets Port 1.0 (red LED) Port 1.6 (green LED) to ON, so that they are lit.

Let's translate the assembly code to object code!

$ msp430-as -o test.o -mmsp430x2012 test.asm

Now we have test.o, although it's an ELF executable, it won't run on the target device. We'll need to run the linker on it, referring to our memory map file (test.map).

$ msp430-ld -o test.elf -T test.map test.o

Great. Now we've got the ELF executable, which we will upload and run this using the 'mspdebug' tool, as follows:

$ mspdebug rf2500 "prog test.elf"
[..snip snip.]
Programming...
Writing  18 bytes to f800...
Writing  32 bytes to ffe0...
$

Voila, we got the end result. Both the green LED as well as the red one are now lit. A very primitive program indeed, but at least now we've sorted out how to use the GNU assembler/linker along with mspdebug to code assembly for the MSP430 chips. In the next article we'll do something more interesting!

6Jan/110

Diving into the IBM – Invoking ROM BASIC!

The IBM XT 8088 comes with something called "ROM BASIC", however I couldn't seem to access it via MS-DOS.  [Note: Source code now available, see comment below]

Initially, it seemed to be inaccessible unless you are willing to remove the harddrive and reboot.  So I set out on a mission; I wanted to access it from within MS-DOS!  The value of all this?  Weeeell...  Hey, it's a challenge.

I read up on the specific interrupt you need to trigger ROM BASIC, and it is INT 18h.

However, it's not as easy as that. I started up DEBUG, punched a few assembly instructions so I could trigger INT 18h.  It responded, and sure enough I got ROM BASIC.  Unfortunately, the keyboard input was not working at all!

I consulted some friendly peeps at comp.lang.asm.x86 and they told me the whole IVT (interrupt vector table) had to be replaced with the one present before MS-DOS replaces it with its own IVT.  In other words, I needed the default BIOS IVT table, otherwise I would be calling the DOS keyboard interrupt routines instead of the BIOS keyboard routines.

I temporarily removed the harddrive, and started the computer so that ROM BASIC came up.  I then wrote a little BASIC program to dump the entire IVT contents as hexadecimal codes to screen. 100 at a time. Just enough so that I could take a photograph of each screen.  (I don't have any means of connecting the XT to one of my other modern machines!).

Typing it all in on my Mac later, I started to make sense of it, and finally printed it all out, including my prototype 8088 program (yes, on old fashioned paper. And yes, this took way too long and my fingers hurt afterwards).  Tricky stuff. I got some friendly advice from the guys in comp.lang.asm.x86 to keep me going further after nearly giving up (Thanks Bob, Rod, Frank!).  My knowledge of assembly isn't the greatest so this endeavour forced me to learn a whole LOT.

Some glimpses of my assembly code.

Then, I finally got it to work, with keyboard working - as you can see below!

Ok, hmm, I spent way too much time on this!  However, I'm glad it's over and done with now.  I think it's cool that there is so much direct access to the hardware and to the memory with these old machines.  Perhaps it's time to revive my Amiga now.    [PS: Full code will be posted shortly, just need to type it all in]

6Jan/110

Trip to Modalen with my dad

A few days ago I went to Modalen on a photo expedition with my cool dad.  You can see him below!  Weather was great for taking photos..  Sorry that the photos are a bit huge this time, I will avoid that next time I post photos.

6Jan/110

Dusting off the IBM

My dad bought an IBM XT 8088 a long time ago, in the 80s sometime.  This was my first introduction to computing so I have fond memories of this machine.  It clocks in at 4.77Mhz on its Intel 8088 CPU.  A mind-boggling 640kB memory keeps you satisfied for a lifetime.

Being home this Christmas vacation (December 2010) I figured it's time to take it down from the attic and see if it boots up!  I first vacuumed it and cleaned all the circuit boards with a brush, so there wouldn't be a hint of dust anywhere.

I cranked the ol' beast up it and it said BAM.  Followed by a bit of white smoke.  I still don't know what happened, but after the 2nd boot, it booted straight up and started MS-DOS.  However, unfortunately only 192kB of the original 640kB was recognized, so some of the memory chips were clearly faulty.  As for the BAM! sound, it must have come from somewhere else. To my knowledge, RAM chips don't fail with a loud noise and burned scent!

I thus started hunting the faulty chips, and finally found the two sinners.  Two nasty 4164 chips (contains 65536 bits each).   However, this meant that all the other chips on the same bank would have to be taken out as well.  So I ended up with an acceptable 576kB of working memory.

Stay tuned for more exciting vintage computing stories!

5Jan/110

First post!

I now have a new blog...!  Stay tuned....