F# meets the Raspberry Pi

by Pezi 2. March 2013 22:58

I got a Pi for my birthday! A great excuse to get back into electronics.

After unsuccessfully struggling to get the F# compiler to build under the stable version of mono for Debian Wheezy, I realised that F# programs work just fine if you build normally from a windows computer, throw in FSharp.Core.dll in the /bin/ and copy it over. So I have a setup now where I work with VS2012 / Sublime and sync the executable and libraries with WinScp (or indeed the Scp plugin for FAR Manager).

Next up is to get access to the hardware. I built this C library as a shared object, dumped it in with the other binaries of my project and it worked through P/Invoke with no hassle at all ! 

I've quite a bit of electronics experience, so after I did some basic tests that the various I/O pins could be set to output and switch from High to Low, I skipped the traditional "hello world" of hardware (blinking an LED) and figured I'd try something a little bit more ambitious. I have a little LCD screen laying around in my old gear, it's a standard LCD driven by the Hitachi HD4480 LCD Controller. You can use these in 8-bit or 4-bit mode, with the 8 bit mode needing 4 more I/O pins.  I'm using the 4 bit mode because I don't really have that many pins and it's pretty easy (although a little fiddly) to use it in 4-bit mode.  

I'm using a total of 7 I/O pins,  E (enable), RS (switch between command and character mode), RW (I'm not actually using this right now) , and then DB4 through DB7 which are the 4 input bits (they are the higher nibble of the full 8 bits). This is the circuit :

In this schematic the Pi pins relate to the actual physical pin numbers, however in the code a mapping is needed over to what the Pi internally calls its GPIO pins.  I created an enum for this purposes, only containing the pins I am using for now

type GPIOPins =
    | Pin_11 = 17u
    | Pin_12 = 18u
    | Pin_13 = 27u
    | Pin_15 = 22u
    | Pin_16 = 23u
    | Pin_18 = 24u
    | Pin_22 = 25u

For example the physical pin 11 maps to GPIO number 17.  Infact when I first hooked this circuit up and wrote all the code to perform the LCD initilization I couldn't get it to work. Thankfully I happen to have a 16 channel logic analyzer in my scope so I hooked up all the inputs, set it to a single sweep triggering on the rising edge of the Enable pin over 500ms and noticed that the RW pin was always high - strange (I neglected to take a picture of the waveforms for this post :( ).  Turns out that the Pi user manual is WRONG, I have got a slightly later revision of the board where pin 13 is mapped to 27, not 21!

The next bit of code imports a couple of the functions from the C library and creates a couple of mini functions around them

[<DllImportAttribute("libbcm2835.so", EntryPoint = "bcm2835_init")>]
extern bool bcm2835_init()

[<DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_fsel")>]
extern void bcm2835_gpio_fsel(GPIOPins pin, bool mode_out);

[<DllImport("libbcm2835.so", EntryPoint = "bcm2835_gpio_write")>]
extern void bcm2835_gpio_write(GPIOPins pin, bool value);

let fsel pin value = bcm2835_gpio_fsel(pin,value)                        
let write pin value = bcm2835_gpio_write(pin,value)            
let wait (ms:int) = System.Threading.Thread.Sleep(ms)

To use the LCD you write some bits to the data pins, then bring the Enable pin high for a few us then pull it low again ("pulse"). The LCD then does something depending on the input bits. In order to prepare it for 4-bit use I first have to send it a few 0x03 (0011) packets as per the spec indicates. Then I can switch it into 4-bit mode (0x2). From this point on, I can use all the 8-bit commands from the spec. Because I'm running in 4 bit mode I have to send the high nibble first, pulse, then send the low nibble. I wrapped some of the LCD functionality up in a F# record type (note: all this code is just a first stab, everything with hardware is inherently to do with mutating state so I won't be using a lot of the real functional features of the language just yet, but I'll see what I can do about that later)

type LCDCommands =
    | AllLow =          0b00000000
    | Clear =           0b00000001
    | Home =            0b00000010   
    | FourBit =         0b00100000   
    | TwoLine =         0b00001100    
    | DisplayOn =       0b00001100
    | CursorOn =        0b00000001
    | AutoIncCursor =   0b00000110    
    | Line2 =           0xC0
        
type LCD = { E : GPIOPins; RW : GPIOPins; RS : GPIOPins; 
             DB4 : GPIOPins; DB5 : GPIOPins; DB6 : GPIOPins; DB7 : GPIOPins; }
    with 
    member lcd.Pulse() = // toggles enable 
        write lcd.E true; wait 1
        write lcd.E false; wait 1
    member lcd.WriteNibble(value) = // write the lower four bits to the data pins and pulses
        write lcd.DB7 (value >>> 3 &&& 0x1 = 0x1)
        write lcd.DB6 (value >>> 2 &&& 0x1 = 0x1)
        write lcd.DB5 (value >>> 1 &&& 0x1 = 0x1)
        write lcd.DB4 (value &&& 0x1 = 0x1)
        lcd.Pulse()
        wait 1
    member lcd.WriteByte(value) =
        lcd.WriteNibble(value >>> 4) // write high nibble first
        lcd.WriteNibble(value)
    member lcd.Command = int >> lcd.WriteByte

I have captured some of the LCD commands in another enum - some of these have to be OR'd together as per the spec. I've just encoded the ones I'm going to use. The there's the pulse which toggles enable with a tiny delay. Because I'm in 4 bit mode I'll always be writing nibbles with a pulse at the end - the WriteByte function simply writes the high nibble first then the low nibble as the spec indicates. The last function is just a wrapper so I can directly use the LCDCommand enum.

member lcd.Initialize() = // I am only using the (annoyingly fiddly) 4 bit mode
        // assume 1000ms or so has passed since program start up
        // make sure pins are set to output
        fsel lcd.E   true; fsel lcd.RW  true
        fsel lcd.RS  true; fsel lcd.DB4 true
        fsel lcd.DB5 true; fsel lcd.DB6 true
        fsel lcd.DB7 true
        // zero them all out
        lcd.Command LCDCommands.AllLow
        // to start with we are only writing special wakeup nibbles
        lcd.WriteNibble(0x3); wait 5 // as per spec, first call has a 5ms wait
        lcd.WriteNibble(0x3); wait 1
        lcd.WriteNibble(0x3); wait 1
        // now set into 4 bit mode and send 8 bits in 2 nibbles from now on
        lcd.WriteNibble(0x2)
        lcd.Command(LCDCommands.FourBit ||| LCDCommands.TwoLine)     // set 5x8 mode 2 lines
        lcd.Command(LCDCommands.DisplayOn ||| LCDCommands.CursorOn)  // switch it on
        lcd.Command(LCDCommands.AutoIncCursor)

This is the startup sequence - set all the pins to Output, zero them all out, and then follow the startup sequence as per the spec. initially I have to just use nibbles, until the wake-up sequence is complete, then I can set it to 4-bit mode and use full byte commands. Once the display is in 4-bit mode I switch it to 5x8 mode with 2 lines and switch the screen on with a flashing cursor and so on.

member lcd.WriteText(text:string,clear) = 
        if clear then lcd.Command(LCDCommands.Clear)
        write lcd.RS true; wait 1
        Encoding.ASCII.GetBytes(text) |> Seq.iter(int >> lcd.WriteByte)
        write lcd.RS false; wait 1

Lastly a function to output some text. To do this you have to set the LCD into character output mode by pulling RS high; then you can send ASCII codes and the LCD will print them.

Pulling this all together I wrote that classic silly number-guessing game you write when learning to program, with the output on the LCD:

[<EntryPoint>]
let main argv = 
    try
        match bcm2835_init() with
        | true ->
            let lcd = { E = GPIOPins.Pin_11; RW = GPIOPins.Pin_12; RS = GPIOPins.Pin_13; 
                        DB4 = GPIOPins.Pin_15; DB5 = GPIOPins.Pin_16; DB6 = GPIOPins.Pin_18; DB7 = GPIOPins.Pin_22 }
            
            wait 1000
            lcd.Initialize()
            
            let rec loop number attempts =                
                 try
                    let guess = Console.ReadLine() |> Int32.Parse
                    if guess = number then                     
                        lcd.WriteText("CORRECT!!",true)
                        lcd.WriteByte(0xC0); 
                        lcd.WriteText("YOU WIN!",false)
                    elif attempts + 1 > 5 then
                        lcd.WriteText("WRONG!!",true)
                        lcd.WriteByte(0xC0);
                        lcd.WriteText("YOU LOSE!!",false)
                    else
                        lcd.WriteText("WRONG!! ",true)
                        lcd.WriteText((if number < guess then "< " else "> ") + guess.ToString(),false)
                        lcd.WriteByte(0xC0); wait 2
                        lcd.WriteText("GUESS AGAIN!",false)
                        loop number (attempts + 1 )
                 with
                 | _ -> printfn "Number not reconigsed. Try again"
                        loop number attempts
                        
            lcd.WriteText("Guess a number",true)
            lcd.WriteByte(0xC0); wait 2
            lcd.WriteText("0 <---> 50",false)
            loop (System.Random(DateTime.Now.Millisecond).Next(51)) 0

            
        | false -> printfn "failed to init"
    with
    | ex -> printfn "exception thrown : %s" <| ex.ToString()
    
    Console.Read()

Here's a pic of it working ..

Cool! This was just a silly project to test everything is working properly - I can take over the world now. 

PezHack–Abstracting flow control with monads

by Pezi 13. July 2012 23:10

It’s been forever since I last posted, I worked quite a bit on PezHack and then stopped for a while.  I’m back to it now.  In this post I will describe a technique I used to greatly reduce the amount of code and abstract away some repetitive imperative code.

The Problem

PezHack is a turn based game. The screen does not re-render itself all the time like a real-time game, but only when something changes and at the end of a the player’s turn.  The agent-based approach I used to separate the various sub systems of the game allow me to provide isolation around the graphics processing.   The graphics agent is totally responsible for knowing what it needs to draw and will draw it on demand when it receives the relevant message.  It does not really know anything else about the game state at all except the visual data of the various tiles that are visible, some player data that allow it to draw the various data about the player, and any menus / other UI that it needs to draw.  Other systems can send it messages to inform it of some new visual state it should care about.

Most actions that Pezi can perform require some form of additional input and conditional flow logic.  For example, when you press the ‘e’ key to Eat, first a menu is displayed that shows the stuff in your inventory that is edible, if possible. If not it will display a message and not end the player’s turn.  Assuming the menu is displayed, the player then presses the key that relates to the item they wish to eat from the menu.  If this key is invalid a relevant message is displayed, else the item in question is eaten. What then happens is dependent on the item, it might provide sustenance, or if it’s a mushroom it could perform one of various kinds of effects, and then probably end the player’s turn

This is a common pattern that appears everywhere, and at each stage the graphics need to be re-drawn to show the various messages, menus and so on.  At each stage it might continue or it might not depending the player’s input, and the returns differs at each stage (end the player turn, or not, for example).  In an imperative language we would almost certainly model this control flow with a bunch of nested if/then/else statements which quickly gets ugly.  Because I am using the agent based approach for the graphics, I would also need to post a request to the graphics agent each and every time I needed the changes to show on the screen, so suddenly the actions become a list of imperative statements peppered with common code to keep the screen updated. 

 

The Solution

This can be drastically improved with the use of a fairly simple monad.  The Maybe monad allows you to remove flow control elements such as nested if / then / else statements, so my monad is based around the Maybe monad with some extra stuff built in to help handle graphics and input. It have called it the Action monad and it works as follows.

  • You supply it two functions and a tuple.  Before, InputPred and Fail 
  • Before is of type (unit->’e) and it is immediately executed with its result bound to a value
  • A cycle is then entered that displays any messages in the queue and draws the screen.  If there are more than three messages, it only shows three and prompts the player to press <space> to show more.
  • Next, InputPred of type (‘e->’f option) is applied the the result of Before
  • If this results in Some ‘f then the monad binds successfully and will continue  with the next expressions, passing along the ‘f result.
  • Otherwise, it looks at the tuple Fail of type (string option * ‘g).  If a string is supplied it is passed to the graphics engine and the message cycle is entered until all messages are processed, and it finally returns ‘g  (in the future i might just make this a function, but at the moment all fail cases only need to show some message to the user rather than perform some other action)

As you can see it is quite generic, and it turns out this monad is quite useful in a variety of areas of the game, not just for actions. I ended up replacing a large part of the core game loop and significantly simplifying it. Here is the code for it first :

type ActionBuilder(graphics:Graphics.GraphicsProcessor) =
    member this.Delay(f) = f()
    member this.Bind((before, inputPred, fail), f) =
        let result = before()
        // cycle through any pending messages that might have been created in before() (or before before!)
        let rec pending state =
            let more =
                if state then graphics.ProcessStatusMessages()
                else true
            graphics.Render()
            if more then 
                let c = TCODConsole.waitForKeypress(true)
                if c.KeyCode = TCODKeyCode.Space then pending true
                else pending false
                
        pending true
            
        match inputPred result with
        | Some(x) -> f x
        | None ->
            if  Option.isSome(fst fail) then graphics.QueueStatusMessage ((fst fail).Value) Common.NormalMessageColour
            pending true
            snd fail
    member this.Return(x) = x

Now let’s see how this is used. First I will show the simplest action, which is quit.  When the quit key is pressed, a message appears asking if they really want to quit, and if they then press ‘y’ then a QuitGame response is issued.

let QuitAction (action:ActionBuilder.ActionBuilder) p = action {
        let! _ = ((fun () -> p.g.QueueStatusMessage "Are you sue you wish to quit? y/n" Common.NormalMessageColour),
                  (fun _ -> let c = libtcod.TCODConsole.waitForKeypress(true)
                            if c.Character = 'y' then Some(true) else None),(None,End))
        return QuitGame}

The Before function displays some text asking if the user really wants to quit the game.  The next function then waits for a key press, and if it;s a ‘y' character then Some is returned (with true, just because it needs to return something, even though we don’t care about it).  If they press anything else, then None is returned, which means the last parameter (None,End) is acted upon, which means it prints no text and returns the End message. This stops the action message at that point and End does not end the player’s turn so they are free to do something else before the monsters move.  Assuming they press ‘y’, the rest of the function executes and returns the QuitGame message which eventually results in the game ending.

Now I will return to the Eat action explained above as its significantly more complex:

let EatAction (action:ActionBuilder.ActionBuilder) p = action {                
        let! items = ((fun () -> p.d.Inventory.FilterType (function ItemData.Comestible(_) | ItemData.Mushroom(_) -> true | _ -> false)),
                      (fun comestible -> if comestible.Count > 0 then Some(comestible) else None),(Some "You have nothing to eat", End))        
        let! id = ((fun () -> p.g.DisplayMenu "Eat what?" (ItemData.Inventory.ToMenu items) ""),
                   (fun () -> let c = TC.waitForKeypress(true)
                              items |> Map.tryFindKey( fun k v -> v.Letter = c.Character)), (Some "The things squirrels will try and eat..", End))
        match items.[id].Type with
        | ItemData.Mushroom(data) ->             
            p.w.AddOrUpdateEntity <| (p.k,World.UpdatePlayerData p.p {p.d with Inventory = p.d.Inventory.RemoveItem id }) 
            Items.MushroomAction data <| (p.e,p.w,p.g,p.k)
            p.w.IdentifyMushroom data
            return EndPlayerTurn 1
        | _ -> failwith ""; return End }

The monad is invoked, with the Before function which filters the players inventory to stuff that is edible. The results of this are then passed into the input predicate function (the wonders of type inference make this just work with no type annotations) and checks if the filtered items contain any data, if they don’t it returns None and then finally the message is displayed indicating the player has nothing to eat, and execution halts there returning End (allowing the player to do something else this turn).  Assuming there were items, they are now bound to items.  Another action monad is then invoked that displays a menu containing the filtered items in the Before function. The input pred then takes player input, if it doesn’t match a letter assigned to the item in the menu it prints a message and returns End. otherwise, id is bound to the id that the player selected.   Finally, the item has some action invoked on it – in this case only mushrooms are implemented, and it removes the mushroom from the players inventory (sending commands to the World agent telling it to update the player data), invokes the mushroom’s specific action, issues another message to tell the World agent that this type of mushroom has now been identified, and finally returns a message that says the player’s turn ends for 1 turn.

Pretty cool! The code above is only interested in the higher level stuff that is going on and doesn’t need to care about display and flow control. Data from the first function can be passed to the second function, and early exit of the function is easily possible. The monad significantly reduced the actions code from almost 1000 lines to less than 350, and that includes Eat, Pickup, Drop, Move, Attack, Throw, Descend Level, Quit, Open, Close, Inventory, Wait, plus functions to merge items that have been dropped or thrown with existing stackable items on the floor where they land,  selection menus and “modal” choice menus, plus various other helper functions. 

Some actions such as Throw are really quite complex, you have to pick an item to throw, choose a direction to throw it, then show it being “animated” as it moves along the screen, and then finally (maybe) hit something, and either drop to the floor or attack an enemy which may result in other things happening – now I can just look at the code and see what it’s doing without having to dig about in a lot of essentially redundant nested code.  Actions can also transfer execution to and from other actions.

Functional programming for the win Smile