# Lecture 15 - Notifier/Server, UART Interrupts

## Public Service Annoucements

1. Kernel 4 revisions.

# Serial I/O

### Providing I/O for the terminal

Initialization

1. Enable RcvRdy, XmitRdy interrupts in UART.
2. Enable combined interrupt in ICU

#### Receiving

Notifier EVT_BL on RcvRdy event

1. Interrupt occurs, AwaitEvent returns with received byte.
2. Notifier Sends byte to server
3. Server Replys,
4. Notifier returns to the EVT_BL state
5. After a while server runs again
insert( ByteQ, byte );
if ( ! empty( ClientQ ) ) Reply( extract( ClientQ ), extract( ByteQ ) );


When server receives Get request from client:

    insert( ClientQ, client );
if ( !empty( ByteQ ) ) Reply( extract( ClientQ ), extract( ByteQ );


#### Transmitting

Transmitting is a little more tricky because two conditions must be met.

1. Byte available to transmit
2. Transmit holding register empty

Assume we put conjunction detection in the server

When server receives Put request from client

    insert( ByteQ, byte );
if ( notRdy ) { notRdy = false; Reply( notifier, extract( ByteQ ) ) }


    if ( empty( ByteQ ) ) notRdy = true;
else Reply( notifier, extract( ByteQ );


The Notifier

Typical Notifier pseudocode:

1. Enable XmitRdy interrupt
	AwaitEvent( XmitRdy );

2. Disable XmitRdy interrupt in UART
	Send( server, ready, byte );

3. Write byte on UART

This procedure assumes that the transmit bit never resets once it is set. Is this true?

Conjunction detection and buffer could just as easily be in the Notifier.

#### How should we handle a terminal?

1. Line editing
• undefined intermediate states
• well-defined trigger

Echo -- Either

• one server per channel,
• passing characters from one notifier to the other
Or
• courier connecting receive server to transmit server
• What characteristics does the terminal have? termcap follies

Many other issues come up later in the course as we consider possible task structures.

### Providing I/O for the train controller

As Above

#### Transmitting

For transmitting three conditions must be set

1. Byte available to transmit
2. Holding register empty
3. CTS asserted

## Primitives for Serial I/O

We are supposed to support

    int Get( int port )

and
    int Put( int port, char c )


These are wrappers for sends to one or more serial servers.

• On Get the server blocks the client until data is available
• Put is non-blocking. The only guarantee is that the character has been added to a buffer of characters to be transmitted

You will probably want something more complex in addition to Get and Put.

## Timing Inconsistencies

#### CTS timing.

What you expect to occur when sending to the train controller

1. The train application puts a byte in the hold register.
2. The stop bit is transmitted.
3. A train xmit interrupt occurs.
4. The train application checks CTS.
5. If CTS is set, you put the next byte in the hold register.

Sometimes an implementation based on this expectation surprises you. In reality what happens when you are sending to the train controller is the following.

1. The train application puts a byte in the hold register.
2. The stop bit is transmitted.
3. Two things happen in parallel
• The train controller checks the stop bit and cleans up.
• The train controller negates CTS.
• When a buffer is cleared the train controller reasserts CTS.
and
• A train xmit interrupt occurs.
• The train application checks CTS.
Because they occur on separately clocked machines no guarantees exist about the order in which these actions will be interleaved. deterministic order. Thus the result of the following action is not deterministic.
4. If CTS is set, the train application puts the next byte in the hold register.

#### Terminal Control Code Timing

The control codes you send to the terminal to move the cursor, blank the display, &, are byte sequences, mostly two bytes long. Consider the following scenario.

1. You discover that your train application is spending too long writing to the terminal, and decide to speed it up using the FIFO.
2. Turning on the FIFO solves the terminal problem.
3. About a week before the final demo, after the train application has been running for 1 to 5 minutes, the terminal display messes up to the point where you can no longer enter commands.
What's the problem?

It might be a problem with output to the terminal.

• When the transmit interrupt occurs it is safe to put eight bytes into the fifo.
• Sometimes the last byte(s) put in the fifo are an incomplete control code.
• Sometimes you are delayed putting the next eight bytes into the buffer.
Then, sometimes-squared, the terminal times out waiting for the remainder of the control code, and takes the next character as ordinary ASCII text, which it writes without having moved the cursor.

# Train Properties

## Location: Where am I?

The usual answer is a combination of a landmark plus a measurement.

• "I'm half a block past the big tree."

To get the second part of the answer you can

• measure explicitly, by eye or with a tape measure, or
• integrate velocity over time.
• Your train application uses the second. You (and we) check the calculation using the first.

## Train Philosophy

You can't do anything until you know where the train is. You accomplish this by

• Knowing the train's location when it arrives at a landmark, and
• Interpolating between landmarks by knowing the train's velocity all the time.

Measurement is costly, and you should squeeze every bit of information you can out of every measurement you make.

• By analogy with human information processing, I recommend that every time you get a sensor report you make a prediction
• Which sensor do you expect to hit next?
• When do you expect to hit it?
• When you hit the next sensor you automatically have an estimate of how fast you travelled between the sensors.
• This estimate is your most recent estimate of the train's velocity on that piece of train, at that speed.
• Using it to improve the calibration tables is what we call dynamic calibration.
• Display the difference between your prediction and your measurement on the terminal,
• in time,
• in distance,
• in velocity

This gives you an ongoing feeling for how your application is working, which is very important for setting effective tolerances.

## Train Measurement

A locomotive travels on the track at a given speed following the path created by directions of turn outs. Where is the train?

• As it travels it triggers sensors that give you feedback as to where it is.
• This is the only direct information you get about train location. The rest you must infer.
• Einstein (1905) tells us that a triggered sensor does not tell you where the train is, but where it was. There is a time lag.
• Train triggers sensor at t: x(t) = Sn + 0 cm
• Report of sensor is recorded (time-stamped) at t + \Delta t. dt includes
• interval between time of triggering and next sensor query
• time for train controller to process query and return the result
• time in your application between receiving bytes from train controller and packaging bytes into a time stamped event

You should be able to estimate each of these time intervals

• At t + \delta t: x(t + \Delta t) = Sn + \Delta x
• \Delta x = \int_t^(t+\Delta t) v(t') dt' ~= v(t) \Delta t
• In the event time-stamped at t + \Delta t the train appears to be at Sn, but it is actually at Sn + v(t) \Delta t
• Does this matter?
• How fast do trains go? Estimate 40 cm/sec.
• If \Delta t is 100 msec you are off by 4 cm.
Please do not pay any attention to Einstein. Newton gives us all the physics you need. Einstein is mentioned only to let you know that you are among the greats!

### Measurement Noise

You do not get the same answer every time you measure. Here's why.

Measurement is tn, Sn

Actual location is Sn + v \Delta t = Sn + v (Mean delay) + v (Noise in measurement)

A second measurement is tm, Sm

Actual location is Sm + v \Delta t = Sm + v (Mean delay) + v (Noise in measurement)

Difference between measurements is tm - tn, Sm - Sn + 2 v (Noise in measurent)

How do you know where the locomotive is?

• intermittently, at a sensor
• between sensors, dead reckoning, which means you need to know the train's velocity

Note. I try to be consistent in distinguishing between two closely related concepts: speed and velocity.

• A train's speed is the value you send to the train controller, an integer between 0 and 14.
• A train's velocity is the rate at which it moves along the physical tracks, a real number measured in centimetres per second.

Velocity is controlled by changing the train's speed, BUT, the mapping between speed and velocity is complex.

• Velocity changes are not instantaneous.
• After the speed is changed the train speeds up and slows down gradually.
• Tricks' that make the train stop instantly are not acceptable because they wear out the trains.
• The velocity decreases when travelling over turn outs or around curves.
• The smaller the radius of curvature the slower the velocity.
• Different locomotives travel at different velocities when set to the same speed.
• Velocity of a given locomotive decreases over time
• As the track gets dirty.
• As the time since the locomotive's last lubrication increases
• As the locomotive gradually wears out

Important. Some of these effects matter; some don't. It's part of your task to find out which is which.

Furthermore, things can go wrong, such as

• A turn-out switches while a locomotive is on top of it.
• You need to estimate where the train will be when the turn-out switches in order to know if it is safe to execute a switch command
• Locomotives run off the ends of sidings.
• You need to know how far a train will travel between when you give the stop command and when the train stops.
• Locomotives stall because they pass over difficult parts of the track too slowly.
• Why? Friction increases when a train is on curved track.
• Sensors fail to trigger, or trigger in the absence of a locomotive
• You need to know when you expect the sensor to be triggered if you are to know that it has not been triggered.

Avoiding such failures, or responding sensibly to them, is possible only if you have a good enough' velocity calibration. (You get a perfect calibration only in the limit t->infinity, and train you are calibrating is dead long before that.) Failures like these also pollute your attempt to acquire reliable data for your calibration.

#### Factors that might effect a calibration.

In general the velocity of a locomotive may be a function of many variables

1. which locomotive it is
2. which speed is set
3. time since the last speed change
4. the velocity at which it was travelling before the last speed change
5. where it is on the track
• possibly on what type of track it is on
6. how long since the track was cleaned
7. how long since the locomotive was lubricated

Important. Some of these effects matter; some don't. It's part of your task to find out which is which.

## 1. Calibrating Stopping Distance

The simplest objective:

• know where the train stops when you give it a command to stop
• restrict the stop commands to just after the train passes a sensor
• only one train moving

Sequence of events

1. Train triggers sensor at $t$
• train at ${S}_{n}$ + 0 cm
2. Application receives report at${t}_{1}=t+{\Delta }_{1}$
3. You give command at${t}_{2}=t+{\Delta }_{1}+{\Delta }_{2}$
4. Train receives and executes command at${t}_{3}=t+{\Delta }_{1}+{\Delta }_{2}+{\Delta }_{3}$
5. Train slows and stops at ${t}_{4}=t+{\Delta }_{1}+{\Delta }_{2}+{\Delta }_{3}+{\Delta }_{4}$
• train at${S}_{n}+y$ cm
• (You measure $y$ with a tape measure.)

• If you do this again, same sensor, same speed, will you get the same answer?
• If you do this again, different sensor, same speed, will you get the same answer?
• If you do this again, same sensor, different speed, will you get the same answer?
• If you do this again, different sensor, different speed, will you get the same answer?
• Or a different train, or different track condition, or ...

1. The sequence of events above has a whole lot of small delays that get added together
• Each one has a constant part and a random part. Try to use values that are diffferences of measurements to eliminate the constant parts.
• Some delays can be eliminated a priori because they are extremely small compared to other delays. The more you figure this out in advance the less measurement you have to do.
2. Knowing where you stop is very important when running the train on routes that require reversing
• Why are reversing routes important?
3. Clearly, knowing when you stop is equally important.

This is very time-consuming!

• The only way to reduce the number of measurements is to eliminate factors that are unimportant.
• The only way to know that a factor is always unimportant is to measure. Developing the ability to estimate quickly, and to find the worst case quickly is the main way of being smart in tasks like this one.

Now make a table

 Sensor 1 Sensor 2 ... Speed 6 Speed 8 ...

There are enough measurements in each cell of the table that you can estimate the random error. (Check with other groups to make certain that your error is not too big.)

Based on calibrations I have seen in previous terms you will find substantial variation with speed setting and train, little variation with sensor.

Group across cells that have the same' value. Maybe all have the same value.

Hint. Interacting with other groups is useful to confirm that you are on track. Of course, simply using another group's calibration, with or without saying so, is academic dishonesty'.

## 2. Calibrating Constant Velocity

At this point there are a few places on the track where you can stop with a precision of a train length or better. However, suppose you want to reverse direction at a switch.

• You want to be close to the switch, clear of the switch, and on the right side of the switch when you stop.
• You want to know when the train has stopped because until then you cannot give the command to throw the switch.
• You want to know when the switch-throwing is complete because until then you cannot start the train running in reverse.

### Knowing the Current Velocity

An implicit assumption you are making is that the future will closely resemble the past.

1. You measure the time interval between two adjacent sensor reports.
2. Knowing the distance between the sensors you calculate the velocity of the train
• velocity = distance / time interval
• measured in cm / sec.

Note that on average the lag mentioned above -- waiting for sensor read, time in train controller, time in your system before time stamp -- is unimportant.

• Sensor1 actually hit at ${t}_{1}$.
• You record (S1, t1 + dt) as the first event.
• Sensor2 actually hit at t2
• You record (S2, t2 + dt) as the second event
• You compute the velocity as (S2 - S1) / (t2 + dt - (t1 + dt)) = (S2 - S1) / (t2 - t1)
• But the variation in dt from measurement to measurement adds noise to the measurement.
3. After many measurements you build a table
• Use the table to determine the current velocity
• Use the time since the last sensor report to calculate the distance beyond the sensor
• distance = velocity * time interval

### Using Resources Effectively

The most scarce resources

• Bandwidth to the train controller
• Use of the train itself

The most plentiful resource

• CPU

Any time you can use a plentiful resource to eliminate use of a scarce one you have a win. For example

### Practical Problems You Have to Solve

1. The table is too big.
• You need a ton of measurements
2. The values you measure vary randomly.
• You need to average and estimate error.

The values you measure vary systematically

• For example, each time you measure the velocity estimate is slower, presumably because the train is moving towards needing oiling.
• You need to make fewer measurements or use the measurement you make more effectively.

## 3. Calibrating Acceleration and Deceleration

### How Long does it Take to Stop?

Try the following exercise.

1. Choose a sensor.
2. Put the train on a course that will cross the sensor.
3. Run the train up to a constant speed.
4. Give the speed zero command at a location that stops the train with its contact on the sensor
5. Calculate the time between when you gave the command and when the sensor triggered.
6. Look for regularities.