Home
Luke's Weblog [entries|archive|friends|userinfo]
Luke Gorrie

[ website | My Website ]
[ userinfo | livejournal userinfo ]
[ archive | journal archive ]

Couchsurfing [Apr. 16th, 2008|11:05 am]
[Tags|]
[Current Location |chiang mai]

Dear European friends!

I'm starting a spring European hacking tour with my favourite Lisp conference in Amsterdam this weekend. My master plan is to bounce around the continent for a month or two visiting the kind friends who offer me their couch or spare room for a week or so at a time.

So! If you're a kind old friend and you'd care to catch up on old times then do drop me an email :-) I'll be hacking away on my circuit board all the while.

I'd particularly appreciate a couch within striking distance of Slussen next week!

LinkLeave a comment

Interrupts [Apr. 8th, 2008|06:17 pm]
[Tags|]
[Current Location |kathmandu]

Today I got interrupt-driven network I/O working.

There's actually a little more to interrupts than I'd realised. We have two separate bits of hardware dealing with them: the CAN network controller sets interrupt signals based on the CAN bus status (data to receive? ready to transmit?) and the Vectored Interrupt Controller (VIC) decides how these signals should affect the CPU's execution.

I'm using the CAN interrupts to track the bus status and using the VIC to temporarily disable interrupts when they're inconvenient, i.e. when I'm accessing a data structure that's shared between ISR (Interrupt Service Routine) and non-ISR code. These data structures are FIFO queues based on the ring code that I posted before.

The tricky part was figuring out exactly when the CAN controller sets and clears interrupt status. Looks like it's based on discrete events (e.g. CAN frame successfully sent on the bus) rather than just conditions (CAN transmit buffer is empty).

Here's the code for receiving data from the CAN bus:

\ Is there a CAN frame ready to receive?
: can-rx? ( -- flag )
    CAN-GSR can@ $1 and  0 <>
;

\ Return the number of bytes of data in incoming CAN frame. 
: can-dlen ( -- n )
    CAN-RFS can@
    16 rshift $F and
    8 min
;

\ Free CAN Rx hardware buffers
: can-ack-rx ( -- ) $4 ( RRB ) CAN-CMR can! ;

\ Receive a CAN frame (blocking)
: can-rx ( -- dB dA len id )
    BEGIN can-rx? UNTIL
    CAN-RDB can@  CAN-RDA can@  can-dlen  CAN-RID can@
    can-ack-rx
;
And here's the interrupt service routine that wakes up when a frame becomes available on the bus and puts it onto the RX queue for application-level processing:
\ Read a CAN frame from the controller and put it on the RX queue.
: can-rx-isr ( -- )
    can-rx-ring ring-full? IF
        can-disable-rx-interrupt
    ELSE
        can-rx can-rx-ring >ring
    THEN
;
Here're the words that non-interrupt code uses to temporarily mask out CAN interrupts to safely access the RX queue:
$4100000 ( CAN1-RX CAN1-TX ) CONSTANT CAN-interrupts
: mask-can{ ( -- ) CAN-interrupts disable-interrupts ;
: }mask-can ( -- ) CAN-interrupts enable-interrupts ;
And here's the non-interrupt code that reads frames from the queue:
: can-dequeue? ( -- flag )
    mask-can{  can-rx-ring ring-empty? not  }mask-can
;

: can-dequeue ( -- dB dA len id )
    BEGIN can-dequeue? UNTIL
    mask-can{
        can-rx-ring ring>
    }mask-can
    can-enable-rx-interrupt
;
How do other people's Forth-based interrupt handlers look?
Link1 comment|Leave a comment

Jones Forth [Apr. 2nd, 2008|01:27 pm]
[Tags|]
[Current Location |ao nang]

Jones Forth is the best program I've read in a long time. It's a complete Forth system written as a literate program by Rich Jones. There are two source files: jonesforth.s, the kernel written in GNU i386 assembler, and jonesforth.f, the higher-level parts of Forth written in itself. Recommended reading! See also the coverage on LtU.

I've truly wasted my life up to now by not programming in the one true language BASIC assembler C Java Scheme Erlang Emacs Lisp Common Lisp Smalltalk Forth!

Link19 comments|Leave a comment

Interrupts [Mar. 29th, 2008|07:31 pm]
[Tags|]
[Current Location |koh phi phi]

Been writing Forth from the hammock for a while now.

I'm reasonably happy with my little interrupt dispatcher which has an interface like this:

\ interrupt service routine for TIMER1 interrupt
: ticker ." tick " TIMER1 clear-timer-interrupt ;

['] ticker int$TIMER1 isr!
int$TIMER1 enable-interrupt
and the machinery looks like this:
\
\ VIC: Vectored Interrupt Controller
\

VARIABLE isr-table 32 cells ALLOT

: isr-entry ( n -- ) cells isr-table + ;
: isr! ( cfa int# -- ) isr-entry ! ;
: isr@ ( int# -- cfa ) isr-entry @ ;

: service-interrupt ( n -- )
    dup isr@   ( n isr|0 )
    ?dup 0<> IF
        execute
        drop
    ELSE
        ." Unhandled interrupt #" . cr
    THEN
;

: ack-IRQs ( -- ) $0 VICVectAddr ! ;

\ Call the ISR for each enabled and asserted IRQ.
: isr-dispatch ( -- )
    VICIRQStatus @
    32 0 DO ( IRQs )
        dup i bit-set? IF
            i service-interrupt
        THEN
    LOOP
    drop
    ack-IRQs
    EXIT-ISR
;

\ Setup generic interrupt dispatching.
: init-VIC
    32 0 DO  0 i isr!  LOOP
    ['] isr-dispatch forth-isr !
    c-isr @ VICDefVectAddr !  \ default non-vectored IRQ handler
;

\ Utilities for ISRs

: clear-timer-interrupt ( TIMER -- )
    $FF swap T-IR + !   ( clear all interrupt flags )
;

: enable-interrupt ( int# -- ) bit VICIntEnable ! ;
For now there's some C glue code to catch the interrupt and call back into Forth and I'm doing the vectoring in Forth instead of the hardware. One step at a time.

To communicate between I/O interrupt handlers and "normal" code I spent most of the day writing a simple ring (bounded buffer) data structure. I'm not thrilled at how much stack-munging code this turned out to be. I reckon that either I didn't write it very well, or I could have taken a much simpler approach in general, or both.

\ Ring data structure to use as a bounded-buffer.
\ The ring is initialized with two parameters:
\   MAX: The most items that the ring can contain.
\   ITEM-SIZE: The number of words per item in the ring.
\ The basic operations are RING-EMPTY? RING-FULL? >RING RING@ RING>
\ Each add/remove from the queue moves ITEM-SIZE words between the
\ queue and the stack.
\ 
\ For example if ITEM-SIZE is 3 then the stack effect of
\ >RING is ( a b c ring -- ) and RING@ or RING> is ( ring -- a b c ).
\
\ The idea is to have an interrupt handler like:
\ : can-send   ( dB dA len id ) can-tx-ring >ring ;
\ : can-tx-ISR ( -- ) can-tx-ring ring> ( dB dA len id ) can-tx
\ where this ring has four words per item.

\ Data structure layout:
\ MAX is the most items that the ring can hold.
: ring-max          ( ring -- addr ) ;
\ FIRST is the index (0..MAX-1) of the first item i.e. next to be taken.
: ring-first        ( ring -- addr ) cell+ ;
\ LENGTH is the number of items currently in the ring.
: ring-length       ( ring -- addr ) 2 cells + ;
\ ITEM-SIZE is the number of words per item.
: ring-item-size    ( ring -- addr ) 3 cells + ;
\ DATA is the start address of the real data area.
: ring-data         ( ring -- addr ) 4 cells + ;
\ See the example down below for how to initialize a ring.

: ring-empty? ( ring -- flag )
    ring-length @ 0=
;

: ring-full? ( ring -- flag )
    dup ring-length @ ( ring len )
    swap ring-max @   ( len max )
    =
;

\ Return the address of the first (next) data element.
: ring-first-addr ( ring -- addr )
    dup ring-first @          ( ring n )
    over ring-item-size @ cells ( ring n size )
    *                         ( ring offset )
    swap ring-data +          ( element-addr )
;

\ Return the address of the last data element. 
: ring-last-addr ( ring -- addr )
    dup ring-first @          ( ring n )
    over ring-length @ +      ( ring n )
    over ring-max @ mod       ( ring n )
    over ring-item-size @ cells ( ring n size )
    *                         ( ring offset )
    swap ring-data +          ( element-addr )
;

\ Copy the elements of the next data element onto the stack.
: ring@ ( ring -- ... )
    dup ring-first-addr swap ( addr ring )
    ring-item-size @         ( addr size )
    0 DO                     ( addr )
        dup @ swap           ( ... v addr )
\        ." fetched " over . ." from " dup . cr
        cell+
    LOOP                     ( v1 .. vn addr )
    drop                     ( v1 .. vn )
;

\ Drop the next element from the ring.
: ring-drop ( ring -- )
    dup ring-length --
    dup ring-first @ 1+  ( ring first' )
    over ring-max @ mod  ( ring first'' )
    swap ring-first !
;

\ Move the next element of the ring onto the stack.
: ring> ( ring -- ... )
    dup >r
    ring@
    r> ring-drop
;

\ Move a data element from the stack onto the ring.
: >ring ( v1 .. vn ring -- )
    dup ring-last-addr            ( ... ring addr )
    over ring-length ++           ( ... ring addr )
    \ insert the elements backwards so that they'll be taken out forwards
    over ring-item-size @         ( ... ring addr elem-size )
    1- cells +                    ( ... ring addr )
    swap ring-item-size @ 0 DO    ( ... addr )
\        cr ." store " over . ." at " dup .
        swap over                 ( v1 ... addr vn addr )
        !                         ( v1 ... vn-1 addr )
        cell-
    LOOP
    drop
;

: .ring ( ring -- )
    cr
    ." max:    " dup ring-max @ . cr
    ." first:  " dup ring-first @ . cr
    ." length: " dup ring-length @ . cr
    ." esize:  " ring-item-size @ .
;

\
\ Test/example code
\

\ Ring for testing
VARIABLE r 4 3 * ( four 3-word items ) 4 + ( and 4 words of header ) cells ALLOT

: init-r ( ) 
    \ Configure the ring
    4 r ring-max !
    0 r ring-first !
    0 r ring-length !
    3 r ring-item-size !
    \ Then you can do e.g.
    \ 1 2 3 r >ring   s:
    \ 4 5 6 r >ring   s:
    \ r ring>         s: 1 2 3
    \ r ring>         s: 1 2 3 4 5 6
    \ etc..
;
Link10 comments|Leave a comment

Forth is bliss [Mar. 22nd, 2008|10:03 am]
[Tags|]
[Current Location |koh phi phi]

I'm programming in Forth on an exotic island and life is just fine. I've done two weeks of serious hacking now: the first to bring up Forth on the Keil MCB2100 board and the second to write drivers and make some extensions to Forth. Serious fun!

Forth is amazing. There's hardly any compiler or runtime system and yet it has all the sophistication of Lisp. This feels like discovering Gödel, Escher, Bach faithfully expressed in a few dozen cave paintings.

The best part about embedded programming is starting from scratch without using a single line of code that we didn't write outselves. Right now we don't have memory protection, dynamic memory allocation, concurrency, garbage collection, etc. So we're going to rediscover first-hand at what point it's worth developing these fancy features. Truly we're retreading some giant steps :-)

Here's some Forth I wrote that may be clever or stupid, I'm not sure which yet:

\ Running time profiling: t( ... )t
: t(
    r> tick      ( r t1 )
    >r >r        ( r: t1 r )
;
: )t
    tick r> r>   ( t2 r t1 )
    swap >r      ( t2 t1 )
    -            ( tdelta )
    . ." ms" cr
;
Ah the rapture of learning a new programming language :-)
Link12 comments|Leave a comment

MCB2100 [Mar. 6th, 2008|06:17 am]
[Tags|]
[Current Location |stockholm]

I've traded in my boring old OLPC XO (everybody has one of those these days) for an exciting new MCB2100 Evaluation Board. This is a 60Mhz ARM7 microcontroller with 16kB of RAM, 256kB of flash ROM, and some fun add-on connectors. The plan is to use my friend Tony's homebrew Forth system and the two Controller Area Network (CAN) interfaces to achieve world domination.

Resistance is futile :-)

Link8 comments|Leave a comment

The end of act one [Feb. 17th, 2008|12:53 pm]
[Tags|]
[Current Location |kathmandu]

Enough with the OLPC for now! I'm off to have some simple fun and let the guys and my most excellent new successor Ties continue the work of bringing green laptops to Nepal. Glory be to all :-)

It's been an experience!

Link5 comments|Leave a comment

So that was 2007 [Dec. 27th, 2007|03:41 pm]
[Tags|]
[Current Location |brisbane]

I'm having christmas in Australia now. My next stop is the C5 conference and talking at the colocated Squeak Party in France (see you there!) Then it's back home to Kathmandu.

Here's a roundup of the later part of my 2007:

I've been a full-time unofficial/unauthorised/unpaid volunteer for One Laptop Per Child since september when I moved to Nepal to help the local effort there. I reckon OLPC will cause a real revolution in education: it'll create the environment in which knowledge spreads naturally between humans (kids, adults, experts) and we'll marvel at the results. With hindsight we'll think that tens of thousands of hours of rigid and sterile instruction is a bit of an insult to human dignity.

But enough about that for now. It's fun to be able to play a tiny part.

We've done a lot while I've been in Nepal. We learned Squeak and found a practical way of working, wrote our initial demo software, found kids to work with, cultivated ties with local schools, created excellent jobs for Nepali programmers, recruited really inspiring people, found help from really generous experts (one of whom even came all the way over to visit us), and started sewing the seeds of really interesting skills that can grow in Kathmandu and then spread out from here. The project continues at a pretty rapid pace.

But there's a lot left to do and lots of things to think about! In particular we need to work on our relationship with the OLPC mothership in Boston. If you're one of them and you're reading this then please get in touch with me and let's find a way to drink beer and talk shop!

Link3 comments|Leave a comment

Been busy [Dec. 6th, 2007|07:06 pm]
[Tags|, , ]

Jumped down a 160m gorge on both bungee and swing.

Adapted to an incredibly comfortable Newari lifestyle: boiled eggs and homemade jam on hot roti for breakfast (with a fresh guava from the tree), excellent family for company, a great pair of dogs to fight with, and a rich and varied feast for dinner every night.

Trekked to remote Rara lake with a highly amusing bunch of people.

Got photographed with my post-trek novelty musketeer mustache (what else to do with 10 days' growth?) and our friends at the department of education.

Did a ferocious Haka at the hash and followed it up with a fairly unhinged expat party.

Took laptops to a school and saw real live kids actually enjoying doing schoolwork! It's SO satisfying to get out of the office and have fun with the kids and teachers.

The whole project is pretty intense: I flow smoothly up to crests (My God this will be fantastic!) and down through troughs (My God this will never work we're doing it all wrong!) and on the whole I love it. This is exactly the kind of hard and miserable fun that I'd missed from startup life. :-)

Next week we've lured the illustrious Bert Freudenberg to visit us and show off some Squeak hacking tricks. We'll also be teaching a one-day workshop of 30 people (programmers, teachers, students, kids) how to develop educational software with Etoys.

Haven't been taking photos!

Link2 comments|Leave a comment

A Farewell to Pong [Nov. 15th, 2007|07:43 pm]
[Tags|, ]

I recently tried to rewrite the MacHack PONG in the XO firmware. I'd just read Thinking Forth so I didn't like the code in PONG.FTH: I wanted there to be one screenful of code for each important section (showing the score, taking keyboard input, etc). Then I'd be comfortable with writing the two-line feature that Mitch Bradley had suggested adding.

What really happened is that I had a lot of fun, learned a lot of Forth, didn't finish the game, and made absolutely no useful contribution to the PONG on the XO. Not too bad as far as failures go. :-)

Anyway I'm an old Amiga guy so I wanted the game logic to execute in lock-step with the screen refresh, and since the vertical blanking period is very short I used double-buffering to avoid flicker:

\ PONGDBUF.FTH: Simple double-buffer support.

: db-fill-rectangle ( col x y w h -- )
   rot screen-height + -rot  ( col x y' w h -- )
   fill-rectangle
;
: wait-vblank ( -- )
   gp-wait-ready
   0 0 wh!  0 0 dst!  0 0 src!
   h# 6000.00cc ropmode!
   h# 400 blt!
;
: db-blit ( -- )
   wait-vblank
   0 screen-height  0 0  screen-width screen-height 20 - gp-move
;
And with lots of effort I did eventually manage to draw the score using only a screen of code, though I reckon it should have been simpler and more direct:
\ PONGSCOR.FTH: Text drawing
decimal
h# ffff constant fg
h# 0000 constant bg

" ****.   *.****.****.*  *.****.*   .****.****.****."
" *  *.   *.   *.   *.*  *.*   .*   .   *.*  *.*  *." $cat2
" *  *.   *.   *.   *.*  *.*   .*   .   *.*  *.*  *." $cat2
" *  *.   *.****.****.****.****.****.   *.****.****." $cat2
" *  *.   *.*   .   *.   *.   *.*  *.   *.*  *.   *." $cat2
" *  *.   *.*   .   *.   *.   *.*  *.   *.*  *.   *." $cat2
" ****.   *.****.****.   *.****.****.   *.****.   *." $cat2
" --------------------------------------------------" $cat2 drop
   constant drawing-instructions

variable ip variable xloc variable yloc

: fill-box ( color -- ) xloc @ yloc @ 10 10 db-fill-rectangle ;
: draw-digit ( x y digit )
   10 mod  5 *  drawing-instructions +  ip !
   yloc !   xloc !
   begin   ( Empty )
      ip @ c@ dup case
         ascii * of  1 ip +!  fg fill-box  10 xloc +!  endof
         bl      of  1 ip +!  bg fill-box  10 xloc +!  endof
         ascii . of 46 ip +!  -40 xloc +!  10 yloc +!  endof
      endcase
   ascii - =  until
;
: draw-score ( x y score )
   >r 2dup swap 50 + swap       ( x y x' y r: score )
   r@      draw-digit           ( x y      r: score )
   r> 10 / draw-digit
;
hex
Drawing the board, bats, and ball was no problem at all:
\ PONGDRAW.FTH: Drawing non-text graphics
decimal

: units ( n -- n ) 20 * ;
: unit  ( n -- n ) units ;

: draw-ball ( x y -- ) fg -rot 1 unit 1 unit  db-fill-rectangle ;
: draw-bat  ( x y -- ) fg -rot 1 unit 6 units db-fill-rectangle ;
: draw-bat1 ( y -- )                 1 unit swap draw-bat ;
: draw-bat2 ( y -- ) screen-width 2 units - swap draw-bat ;
: draw-score1 ( score -- )                100 40 rot draw-score ;
: draw-score2 ( score -- ) screen-width 200 - 40 rot draw-score ;
: draw-centerline ( -- )
   fg  screen-width 10 - 2 /  40  10 screen-height 80 -  db-fill-rectangle
;
: draw-boundary ( y -- ) >r  fg 0 r> screen-width 20 db-fill-rectangle ;
: draw-boundaries ( -- ) 0 draw-boundary  screen-height 20 - draw-boundary ;

: fill-screen ( color -- ) 0 0 screen-width screen-height db-fill-rectangle ;
: draw-screen ( bat1-y bat2-y ball-x ball-y score1 score2 -- )
   bg fill-screen  draw-boundaries  draw-centerline
   draw-score2 draw-score1
   draw-ball draw-bat2 draw-bat1
;
: test-draw-screen ( -- ) 200 500 800 500 72 48 draw-screen ;

hex
The keyboard code fits in one screen but it's the one part I mostly borrowed from the original:
\ PONGKDB.FTH: Keyboard input
decimal
0 value key_esc        0 value key_off
0 value key_left_down  0 value key_left_up
0 value key_right_down 0 value key_right_up

: initkeys    ( -- ) " stdin @ iselect  ' get-scan  0 alarm  iunselect" eval ;
: restorekeys ( -- ) " stdin @ iselect  ' get-scan 10 alarm  iunselect" eval ;
: clear-key-states ( -- )
   false to key_esc         false to key_off
   false to key_left_down   false to key_left_up
   false to key_right_down  false to key_right_up
;
0 value e0-seen?
: set-key-states ( down? station )
   dup . dup 1 = if abort" quit" then  case
      h# 65 of  e0-seen? if to key_right_up   else to key_left_up   then  endof
      h# 66 of  e0-seen? if to key_right_down else to key_left_down then  endof
      h# 69 of  to key_esc        endof   \ lower left game button
      h# 2a of  to key_left_up    endof   \ shift-left
      h# 5b of  to key_left_down  endof   \ hand-left
      h# 36 of  to key_right_up   endof   \ shift-right
      h# 5c of  to key_right_down endof   \ hand-right
      h# 5d of  to key_esc        endof   \ square
      h#  1 of  to key_off        endof   \ ESC scancode
   endcase
;
: scan-keyboard ( -- )
   clear-key-states
   begin " get-data?" stdin @ $call-method  while   ( scancode )
      dup h# e0 =  if
         drop  true to e0-seen?
      else
         set-key-states  0 to e0-seen?
      then
   repeat
;
hex
And then the game logic itself -- well, that's where I stopped, because I got stuck chasing a bug that somehow locked up the keyboard soon after the game starts:
\ PONGGAME.FTH: Game state
decimal

variable bat1-y variable bat2-y variable ball-x variable ball-y
variable ball-dx variable ball-dy
42 value score1 0 value score2
: step-ball ( -- ) ball-dx @ ball-x +!  ball-dy @ ball-y +! ;

: game-draw ( -- )
   bat1-y @ bat2-y @ ball-x @ ball-y @ score1 score2 draw-screen
;
: game-loop ( -- )
   begin
      scan-keyboard
      key_left_up    if -10 bat1-y +! then
      key_left_down  if  10 bat1-y +! then
      key_right_up   if -10 bat2-y +! then
      key_right_down if  10 bat2-y +!  ascii x emit then
\      3 ball-x +!  1 ball-y +!
      game-draw  db-blit
      random d# 10000 mod 0= if 1 to key_off then
   key_off  until
;

: pong-display-test ( -- )
   d# 100 0 do  test-draw-screen db-blit  loop
;
: pong-game ( -- )
   initkeys  game-loop  restorekeys
;

hex
There it ends, and I'll never finish it now that I'm having more fun programming in Etoys. So it goes!
Link12 comments|Leave a comment

Gone trekkin' [Oct. 17th, 2007|06:30 pm]
[Tags|, ]

We've been hacking but now it's time for a trekking holiday!

Freedom is overrated: now I'm on board to hack for the OLPC effort in Nepal for a whole year. Oh the plans I had.. but this will be amazing stuff! Since the guys in Boston produced enough miracles to build this lovely little green machine I reckon it's the least we travel-loving programmers can do to jump on a plane and help put it to use.
Link2 comments|Leave a comment

Etoys [Sep. 21st, 2007|08:42 am]
[Tags|, ]

I've been learning more Etoys lately and it's extremely cool. I didn't understand it at all the first few times I played with it but now I can teach it to somebody else in an hour. The demos involve a lot of smiling and laughing :-)

The downside is that I don't know a good way to "get" it all by yourself. There really needs to be a cool demo and ideally someone you can play along with to get started. This would seem to limit how well it can spread, but on the upside it means I can travel around the world giving cool and surprising demos to people. :-)

I've started digging a little bit into the implementation. I hate to say it but even after quite some exposure I still find Smalltalk/Squeak/Morphic code by far the hardest to understand. As a Lisp/Erlang/C/etc programmer I expect to be able to print out the listing for some major concept (viewer, player, etc), read it form start to finish, and basically understand it. But Squeak code is a complex graph (twisty maze). My friend Juho rightly pointed out over beer that since I know basically how I want the program linearised (depth-first into subroutines) I should probably stop whining and write a custom Smalltalk browser. I wonder if this has been done, or if a little more mastery of the cross-reference features will make the idea seem silly. We'll see.

We're recruiting an Etoys programming and design team here in Kathmandu to write Squeak-based educational software. Should be fun :-)

Link4 comments|Leave a comment

Etoys [Sep. 21st, 2007|08:33 am]
I've been learning more Etoys lately. It's extremely cool: I didn't understand it at all the first few times I played with it but now I can demo and teach it to somebody else in an hour. The demos involve a lot of smiling and laughing :-)

The downside is that I don't know a good way to "get" it all by yourself. There really needs to be a cool demo and ideally someone you can play along with to get started. This would seem to limit how well it can spread, but on the upside it means I can travel around the world giving cool and surprising demos to peoople. :-)

LinkLeave a comment

Kathmandu [Sep. 16th, 2007|01:27 pm]
[Tags|, , , ]

Kathmandu is great!

In the few days since I landed I've done productive work at the newly-forming OLE Nepal, explored Thamel, been introduced to the nightlife (good), Hashed around the edge of Kathmandu valley, and now I'm having a relaxing sunday breakfast with good coffee and wifi at the Himalayan Java Cafe.

Kathmandu is great value. You can find a clean room in Thamel for $2/night and a good all-you-can-eat meal of Dahl Baht for about $0.50. Best of all is that you can eat with your hands. :-)

There was one day of productive work so far: I was introduced to Christine the teacher-trainer and found out how she'd like to computerise a couple of simple maths/english textbooks that she wrote. I tried prototyping the first bit (a grade #1 adding exercise) with Etoys and this was really pleasant. Just by dragging and dropping some stock objects and pictures from the internet I easily made a simple authoring environment for creating a book of adding exercises. There're only three lines of drag'n'drop code to indicate whether the answer is correct, see screenshot!

A little polish is needed and then it'll be fun to see how it's received. I'm glad there's productive work to be done from day one.

Link4 comments|Leave a comment

The adventure continues.. [Sep. 10th, 2007|09:20 am]
[Tags|, , ]
[Current Location |wadi musa, jordan]

I've now spent six weeks taking it easy and kicking around in the middle east. "Real life" is a fairly distant memory by now. :-)

The focal point has been visiting my friend and history tutor :-) Denis Mashkevich, the philosopher and Lisp programmer of Jerusalem. I also caught up with the west-coast Lisp scene (Michael Livshin) and even the illustrious Ehud Lamm! I hadn't met Ehud before and it was great to find we have so much in common.

I also made some new Hollywood friends along the way who I'm looking forward to meeting up with once my eastward trajectory lands me in California. :-)

Now I'm exploring around Petra (again) and rediscovering the wonderful truth that the whole world smiles back at the guy on the unicycle. :-) Yesterday I rode from Wadi Musa down through the Beduin village to Little Petra and spent some hours hiking in the mountains. It was all smiles and jokes for the whole day and lots of people waved me down to offer tea while they tried their luck at riding. So, so, so much fun :-)

The unicycle is an excellent instrument for measuring the overall societal whimsy level. The Jordanians score very well: right up there with the Russians!

Photos: around Israel, brilliant scuba diving holiday to Dahab, around Petra.

Tonight I'll fly from Amman towards Kathmandu to start on some real work!

Link3 comments|Leave a comment

Leisurely XO'ing [Sep. 4th, 2007|08:01 am]
[Tags|]
[Current Location |tel aviv]

I'm lurking around the middle east: hacking Forth, diving the red sea, taking up space in comfy cafes, etc. For weeks now the XO has been my primary computer and I'm writing this blog entry on it. I do love this little machine but it'll take some more time before I can set productivity records using it :-)

For hacking I mostly live in Open Firmware without booting the operating system, but by now it's a bit lonely hacking away in there when nobody around me has another XO to hack alongside. Hopefully we can start an Open Firmware hackers club in Kathmandu! I'll be there in a week and I hope to meet as many local hackers as possible over the autumn.

For other computer usage I've converted the XO into a basic Fedora box simply by editing /etc/inittab to start at runlevel 3 (i.e. not start Sugar) and doing 'yum install' of some essentials (ratpoison, firefox, gv, etc). Squeak runs reasonably well too, I've installed the standard "dev" image. I'm using tiny shell scripts to fiddle /sys for things like switching the screen into black-and-white reflective mode.

The screen is really beautiful in greyscale mode with reflected sunlight, even here in the shade near some open windows. I'm disappointed each time the sun sets and I have to switch into backlit-mode. Picture it: the next generation of hackers habitually rising with the sun to hack fiendishly in open, airy places until sunset.
Link1 comment|Leave a comment

boing boing boing [Aug. 14th, 2007|10:33 am]
[Tags|, ]
[Current Location |austrian hospice, jerusalem]

Today's XO firmware graphics hack makes the screen bounce up and down! To run it you first install a recent firmware (one having graphics processor words) and then type:
25 bouncing
after you've loaded this code of bounce.fth:
screen-ih iselect     \ open display device

: wait-vblank ( -- )  \ wait until the next screen refresh
   gp-wait-ready  0 0 wh!  h# 6000.00cc ropmode!   \ setup NOP
   b# 10000000000 blt!                             \ execute on next vblank
;
: origin-xy ( -- x y ) 0 0 ;
: screen-wh ( -- w h ) screen-width screen-height ;
: bounce-setup ( -- )
   gp-setup
   origin-xy  0 screen-height      screen-wh  gp-move
   ffff       0 screen-height 2 *  screen-wh  gp-fill
;
: bounce-step ( speed pos -- speed' pos' )
   over +         ( speed  pos' )
   swap 1- swap   ( speed' pos' )
;
: bounce-draw ( pos -- )
   screen-height +  0 swap  ( src-x,y )
   origin-xy screen-wh      ( src-x,y dst-x,y w,h )
   gp-move
;
: bounce ( init-speed -- )
   bounce-setup
   0 begin
      wait-vblank  bounce-step  dup bounce-draw    ( speed pos )
   dup 0= until  2drop
;      
: bouncing ( init-speed -- )
   recursive  dup 0> if  dup bounce  2 / bouncing  then
;
LinkLeave a comment

ed, man! [Aug. 10th, 2007|05:50 pm]
[Tags|, ]

Yesterday I built an OLPC firmware image for the first time. It's easy and rumoured to be fairly safe, all you have to do is type this line from the top of the svn tree:
cd ./cpu/x86/pc/olpc/build; make clean; make
The scrolling speed is gratifyingly fast now that Mitch Bradley committed my Geode accelleration patch! (He rewrote it before doing so, but I'm a newbie so that's to be expected :-))

Now I'm trying to setup a self-sufficient Forth development environment on the XO. I'm quite well adjusted to the keyboard by now so there's no good reason to lug this Macbook around from cafe to cafe just to run Emacs.

The first thing I need is a convenient and persistent way to edit Forth programs on the XO. The programs should be stored on the 2GB SD-memory card that I added so that they're not overwritten when I install a new OLPC software image on the 1GB internal NAND flash. Mitch Bradley already sent me a lot of pointers to get started with file system access (I've put these on the OLPC Wiki as draft Forth Lesson #13) so it's only a matter of building some convenient "editing words" on top.

So I've hacked together something that I'm pretty happy with. Now I write ed foo and the openfirmware text editor (which is minimal but comfortably Emacsish) pops up with the contents of sd:\foo.fth. I edit and then press ^C to finish and optionally save the changes. If I want to evaluate the most recently edited source file I just type ev.

Here's the code:

0 0   2value   ed-file      \ filename being edited
10000 constant ed-maxsize   \ buffer size (max)
0     value    ed-size      \ amount of text in buffer
      create   ed-buf  ed-maxsize allot

: read-content ( adr len name$ -- sz )
   r/o open-file  if  0  else  dup >r  fgets  r> fclose  then
;
: write-content ( content$ name$ -- )
   2dup $delete-all  $create-file >r  " write" r@ $call-method  r> close-dev
;

: name>file ( $n -- $fn ) " sd:\" 2swap " .fth"  $cat2 $cat2 ;
: edit-string [ also hidden ] edit-file [ previous ] ;

: ed$   ( -- s$ ) ed-buf ed-size ;
: ed-read  ( -- ) ed-buf ed-maxsize ed-file read-content  is ed-size ;
: ed-write ( -- ) ed$ ed-file write-content ;
: ed-save? ( -- ) " Save?" confirmed? if ed-write then ;
: ed-edit  ( -- ) ed$ ed-maxsize edit-string is ed-size ;
: ed \ name ( -- )
   safe-parse-word name>file is ed-file
   ed-read ed-edit ed-save?
;
: re-ed ( -- ) ed-edit ed-save? ;
: ev    ( -- ) ed$ eval ;
This feels pretty good so far. I would like to know a way so that I could re-evaluate this source file to pick up new definitions without reallocating all the variables, so that I could preserve the existing state (like DEFVAR vs DEFPARAMETER in Lisp). I don't really understand how Forth people do interactive redefinition of functions yet.

Next target: reading and referencing openfirmware sources without the Macbook.

LinkLeave a comment

Forth: baby steps with Geode [Aug. 7th, 2007|07:06 pm]
[Tags|, ]
[Current Location |jerusalem]

I did my first little odd job on OLPC: making the firmware's console snappier by scrolling the screen using the Geode graphics processor instead of the CPU. This turns out to be really simple using the tiny library for accessing the graphics processor registers:
: ypos ( line# -- y ) char-height *  window-top + ;

: fbgeode-delete-lines ( delta-#lines -- )
   line# + ypos  window-left  swap ( src-x,y )
   window-left  line# ypos         ( src-x,y dst-x,y )
   screen-width screen-height      ( src-x,y dst-x,y w,h )
   gp-move
;

\ Patch geode acceleration into an installed (fb16) framebuffer
: fbgeode-accelerate  ( -- )
   gp-setup
   ['] fbgeode-delete-lines is delete-lines
;   
This improves the speed of inserting a new line of text into the framebuffer from 58ms to 4.5ms.
LinkLeave a comment

XO: demo machine extraordinaire! [Jul. 26th, 2007|10:34 pm]
[Tags|, , ]

Here's my first tiny graphics hack for the XO. If you have one, try this:
  1. Power on the machine while holding down one of the game buttons (next to the screen). Release the game button when instructed.
  2. Press escape (top-left key) to skip the normal boot sequence and go directly to the Forth ok prompt.
  3. Enter this line:
    screen-ih iselect  ff000000 20f580 0 do  dup dup c@ invert swap c!  1 +  loop
    
Wow! Fantastic! The colours on the screen all became inverted! Yeeaaah!
Okay, not so amazing, and the snippet is confusing for a few reasons:
  1. It's optimized to be as few characters as possible so that you kids can type it.
  2. It uses constants for video memory location and screen size. My God, after all these years, a moment of freedom from slavery to portability!
  3. I'm a Forth newbie and I'm probably fumbling around with my stack manipulation.

To be clearer about what's going on, let's rewrite that program by using OFW's macro assembler to convert it into machine code:

code inverse-screen ( -- )
  frame-buffer-adr #  eax mov                \ eax is the increasing memory address
  screen-height /scanline * 4 / #  ecx mov   \ ecx is the loop counter (down to zero)
  begin                                      \ ebx is a temporary
    0 [eax] ebx mov
    ebx not
    ebx 0 [eax] mov
    4 # eax add
    ecx dec
  0= until
c;
Clear now? Good!

.. and now that we have standard hardware we can also once again talk plainly about timings. The Forth version takes around 1284ms to run whereas the assembler one takes around 89ms. Plain and simple!

Link6 comments|Leave a comment

navigation
[ viewing | most recent entries ]
[ go | earlier ]