CSE 466 Lab 8: The Raven Deconstructed

This page, like the final project, is still under development. It will change frequently, so check it often as you are developing your Raven agent. This document, not including linked resources, was last changed on Wednesday, 18 March at 04:24 PM.


In this lab, you will:

Suggested Reading and Resources


The Raven Deconstructed is based on the concept of cellular automata and on the collective behavior of decentralized, self-organized systems. An example of this is the famous BOIDS, which is a visual simulation of a flying flock of birds, where each bird follows simple rules independently.

The variant of using separate physical agents derives from the field of swarm robotics.


We will appropriate the term "poetry slam," or "slam," to refer to our collective behavior in this project.

A Slam is a cloud of sound events of related phrases of a poem, in this case "The Raven" by Edgar Allen Poe, as read by James Earl Jones. The choices and the phrases derive from the execution of a set of common rules, without the intervention of any central control. Therefore, the resultant effect falls under the category of Emergent Behavior.

Slam sound-file phrases consist of several types:

Each set of partners will implement their own version of a “Cooperative compositional agent” using the specifications listed in this document. Your compiled code will run on both you and your partner’s “agents” for the Slams demonstration on the final exam day, 10:30 AM, on Thursday, March 19th in the atrium. Remember you need to qualify your “agent” before it can participate in the Slams demonstration. If for some reason you are unable to qualify your “agent”, an alternative “agent” program will be provided so that you may receive your participation points for the demonstration.

There will also be a dress rehearsal and testing session in the Atrium on Tuesday, March 17 from 6:30 to 10:00 PM.

State Machine

Idle State

This is the state in which your agent should start. In IDLE_STATE, your agent should be listening for control packets from the controller and the user interface should be active, but the agent is not actively participating in the slam.

Wait State

Play State


During several states, your agent must delay. You should choose the amount of time to delay by evaluating the following expression:

	phrase_len - trigvar >> 1 + rand() % trigvar

where phrase_len is the length of the audio file that the new sound is in response to, in milliseconds, trigvar is a global parameter, and rand() is the C function for generating a random integer.

While you are delaying, you should continue to receive and process packets:

You can implement delays with the usleep() call. The delay times do not need to be exact (in fact, some randomness is desirable.) However, don't call usleep() for the entire duration you want to delay; instead, sleep for some small timeslice, perform the tasks that you need to do while delaying, sleep some more, etc. until the entire delay has elapsed.

Rules for Choosing to Play a Phrase

When choosing whether or not to respond to a phrase_message packet by playing another phrase, the following rules should be evaluated.

RSSIfactor is a boolean function of the RSSI of the node that triggered this evaluation of the rules. An RSSI value of a closer node should result in an RSSIfactor of zero, allowing sound to be played. A far away node should result in a non-zero RSSIfactor, meaning that packets from nodes that are too far away are essentially ignored. The exact details of the implementation of this function are up to you.

Phrases are categorized as complete thoughts, subject clusters (nouns), and verb clusters. The choice of which list you will play a phrase from is dependent on the type of the phrase that triggered this evaluation of the rules. The rules for this decision are as follows:

User Interface

You should develop a user interface for your agent using the LED and LCD for output and the SuperBird's switches for input. Your interface should allow for the following:

Try to make your interface efficient. Remember that it will become a part of your agent program, so it should use resources effectively (e.g. don't update the display every time through a tight infinite loop.)

Using the LCD

The LCD driver allows you to put graphics and text on the SuperBird's LCD. It allows you to update a rectangle on the LCD with raw pixel data, with or without an alpha channel, and also to draw text on the display with a few simple bitmap fonts. The driver is available through subversion/trac here. Note that you can download a zip archive of the entire driver at the bottom of the trac page.

Refer to the documentation.txt file in the driver source for information on how to use it. test.c also provides several examples of how to use the driver (make test should build it.)

Using the switches

A new version of the SuperBird driver that implements ioctls for reading the switches, among other things, is available here or as a package here. Documentation and a description of what all of the status bits mean is included in the superbird.h header file, which you should include in your program.

The status of the switches is also available through sysfs in /sys/bus/i2c/devices/0-004d/switches.  This is how the sbstatus application you used to test the SuperBird reads the switches.

Network Protocol

All packets should have the following format:

type src dest pad payload
1 byte 1 byte 1 byte 1 byte 0-24 bytes

src and dest are the node numbers of the transmitter and receiver, respectively. This addressing scheme is independent of the TinyOS MAC layer, which you should always set to broadcast packets (0xFFFF) as you have done with previous labs. pad is an empty/ignored byte to eliminate alignment issues with the packets. The content and length of payload, if present, is defined by the packet type.

To make your code more readable and allow for easy changes to the packet structure, you should define all of your packet types as C structs in one of your header files. By casting a pointer to the data field of a TOS_Msg to your own type that defines the packet structure, you can access the packet fields by name. If we need to change the structure of a packet, you will then be able to do so by just editing the header file instead of fixing a bunch of manual indices.


You will be assigned a node number that will be your slam agent's address. This address should appear in the src field of all packets you transmit, and your agent should ignore packets that are not addressed to it or to the broadcast address.

There are two special node addresses:

Packet Types

This section defines the packet types that your agent must understand.

Set Global Parameter

This packet is a request from the controller for the agent to change one of its global parameters. It should only be accepted from the controller's address.

dest pad id value
1 byte 1 byte 1 byte 1 byte 1 byte 2 bytes


This packet from the controller tells the agent to stop any current sound and go to WAIT_STATE. If the agent is currently in IDLE_STATE and it receives a listen packet, it should go to WAIT_STATE.

dest pad
1 byte 1 byte 1 byte 1 byte

Do Sound

This packet from the controller tells the agent to stop what it is doing, go to PLAY_STATE and to play the sound file indicated in the payload.

dest pad sound
1 byte 1 byte 1 byte 1 byte 1 byte 1 byte


This packet from the controller tells the agent to stop any current sound and go to IDLE_STATE.

dest pad
1 byte 1 byte 1 byte 1 byte

Phrase Message

The phrase_message packet is the main packet type sent out by your agent. It contains information about what your agent is doing, such as the currently playing phrase.

src 0xFF
pad seq
txpower reply
1 byte 1 byte 1 byte 1 byte 1 byte 1 byte 1 byte 1 byte 1 byte 1 byte

Startled Message

This packet is triggered by the accelerometer, and indicates that the receiving agent should stop what it is doing and resend the startled_message packet after decrementing TTL.

src 0xFF
pad startled
TTL seq_num
1 byte 1 byte 1 byte 1 byte 1 byte 1 byte 2 bytes

The Receive Queue

As you receive phrase_message packets, you should store them in an 8-entry circular FIFO queue. The entries in this queue will be used to decide what to do next.

Entries in the queue should contain the following information:

Each new entry should overwrite the oldest entry in the queue. Make sure you initialize the data structure to a reasonable state when it starts out empty at the beginning of your program.

Global Parameters

Your agent should have a set of global parameters that govern its behavior. These parameters should have consistent IDs across everyone's implementations and should be controllable with a set_global_parameter packet from the controller.

Note that the list of parameters and their default values will likely change as the project progresses. Expect new parameters to be added and the default values to change.

ID Name Description Default Value Units
0x00 trigvar 100 milliseconds
0x05 silence probability that this node decides to speak 10 1/x
0x06 hop_count initial TTL for startle messages 3 hops
0x07 tx_power transmit power that this node should use 20
0x08 led_color color of the LED on the SuperBird (3 bytes, 0x0RGB) #000
0x09 echo_probability the probability that this node will echo another 4 1/x
0x0A channel the radio channel that this node is using 11

Part 1: Build your state machine

Build your state machine as shown above. To begin, use a button push to move from state to state, showing the LED color change for each state. Use one button for trigger sound, another button for playing a phrase. Use the accelerometer to cause the startle sound.

Add code to handle and create the packet types defined in the specification document.

Part 3: Add Everything Else...

Finish it!

Notes on the TOS MAC driver...

The source is here: TOS_MAC driver source

In SG2_CC2420.h is the following:

#define TEST_CCA_PIN()   (GPLR(SG2_GPIO116_CC_CCA) & GPIO_bit(SG2_GPIO116_CC_CCA))

This is used in CC2420.c in void CC2420_try_to_send()

Let's adapt this for our purposes to determine if it's safe to transmit.