Sorry to resurrect an old thread, but altontoth had sent me a note asking for a bit more detail on my prior posting and had asked that I post to the thread to “share the knowledge”. So, I am.
I don’t know if you are using C or assembler, but I’m going to post assembler as the timing will be much easier to handle. This completely untested code and may not even compile, but it will be a starting point.
//Registers R0, R1, R2 will be your time value.
//XORing a register with itself will zero its value
eor R0, R0
eor R1, R1
eor R2, R2
//R3 will be used as a constant zero
EOR R3, R3
//R10 will be used to track lanes that have started
//R11 will be used to track lanes that have finished
eor R10, R10
eor R11, R11
//configure port B for your starting sensors and port C for
//your ending sensors. This will configure port B and C as
//inputs with pull ups disabled. This means that the lines
//driving the port must have valid logic levels at all times.
//This code will assume that the inputs will go high when
//the start or end sensors are triggered
ldi R16, 0;
mov DDRB, R16
mov DDRC, R16
mov PORTB, R16
mov PORTC, R16
//Register pair X will point to the starting time data. You would
//need to make the constants referred to in the following instructions
//point to somewhere in RAM
ldi R27, START_HIGH
ldi R26, START_LOW
ldi R29, END_HIGH
ldi R28, END_LOW
//Disable all interrupts
cli;
LOOP:
//check to see if any lanes have started. Skip the
//completed part of the check if no lanes have started.
cp R10, R3
breq NO_START_DELAY
//If we have lanes started, check to see if all lanes that
//started have finished.
cp R10, R11
brne NO_START
jmp DONE
NO_START_DELAY:
nop
nop
NO_START:
//Now lets get the values of the start and finish sensors in
//case they change while we are working with them.
mov R16, PINB
mov R17, PINC
//check to see if any lanes have started
cp R16, R3
//We insert a delay to account for the unexecuted instructions
//if we have no lanes started
breq CHECK_FIN_DELAY
//store the lanes that have started
st X+, R16
//now store the time stamp for the start
st X+, R0
st X+, R1
st X+, R2
//set flags for the lanes that have started
or R10, R16
jmp CHECK_FIN
CHECK_FIN_DELAY:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
CHECK_FIN:
//check to see if any lanes have finished
cp R17, R3
breq INC_TIME_DELAY
//store the lanes that have started
st Y+, R17
//now store the time stamp for the start
st Y+, R0
st Y+, R1
st Y+, R2
//set flags for lanes that have finished
or R11, R17
jmp INC_TIME
INC_TIME_DELAY:
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
INC_TIME:
//set the carry flag. When we add zero to the low byte of our time
//stamp the set carry will also be added effectively incrementing by one
sec
adc R0, R3
adc R1, R3
adc R2, R3
//at this point, if the carry is set then we have overflowed our time stamp
//counter and need to exit otherwise we loop back and do the whole thing
//over
brcc LOOP
DONE:
//terminate the series of timestamps for start and end with a set of four
//0x0FF bytes to signify the end of data during read out.
ldi R16, 0x0FF
st X+, R16
st X+, R16
st X+, R16
st X+, R16
st Y+, R16
st Y+, R16
st Y+, R16
st Y+, R16
//When you get here, one of two conditions is true
//1. The timer overflowed before all lanes completed or any lanes started
//2. All lanes that started have completed.
At the end, R10 will have a bit set for each lane that started and starting at the original address pointed to by X, you will have a sequence of bytes with the first byte containing the lanes that started and the next three being the 24 bit time stamp for when they started. Likewise, R11 will have a bit set for each ending lane and starting at the original Y address will be the sequence for ending lanes. You will then need to read out each of the timestamp sequences and send it to the host computer. Each “tick” of the 24 bit timer is going to represent around 41 clock cycles or 0.000005125 seconds at 8MHz. The 24 bit timer would overflow at just under 86 seconds (85.98322…).
I should point out that there is a lot of error checking that is not included. What happens if the start sensor triggers multiple times for the same lane, or the end sensor triggers before the start sensor, etc. The way the code about is layed out, all the program does it collect time stamps for trigger events. It is much simply to let the host computer program do the error checking and stuff. If you do add more error checking to the above code, you have to make sure that the number of clock cycles for every path through the code is the same or timing will differ depending on which path is taken. That is the reason for the NOPs sections in the above code. You could probably reduce the number of clock cycles used with more careful coding, but I figured that 5 millionths of a second was accurate enough. If you need a longer maximum time, you can easily extend the timer to 32 bits.
Hope this helps some.