I thought I would go thru the interrupt routine to give you an idea of what I was trying to do.
The thought is that the interrupt routine will capture the stream of bits in a burst into an unsigned long. The interrupt will not try to figure out what the bits mean. That is the job of the application loop ... to take a completed burst and figure out what the bit pattern means based on the scale protocol.
Note that we don't care ... other than the value in the define ... if the transitions a rising or falling. All we are concerned about is that when a transition happens we are led to believe that the information on the data line is 'valid'.
The first thing we do on a transition is determine the time of the interrupt and how long it has been since the last interrupt. They are both unsigned so we do not need to worry about things like rollover. We do this for all interrupts as only the very first interrupt we see does not care about the interval so lets make life simple.
The next thing we need to do is determine if this is the very first interrupt we have seen since we started the application. If it is the first one we have no idea where were are at with the clock so even our 'last time' does not have meaning and therefore our interval does not have meaning. Lets capture the time and set a couple of "here is where we are" sticks in the ground so we are be ready for the next interrupt.
All of the following interrupts fall thru to the next if. Now that we have a valid 'last time' and therefore a valid 'interval' we can see how long it has been since the last interrupt. If the interval is 'too soon' [we need to look at what we get from the scope to determine some of these values] then we consider it noise and just ignore it.
If it is not noise then maybe it is the beginning of a burst. We identify the beginning of a burst as having been [information from the scope goes here, but a relatively long time] microseconds since the last interrupt. If we think it is the beginning of the burst then do some things to start capturing the bit stream and that's it.
There is the possibility that we find what we think is the beginning of a burst while we are processing a burst. We will punt but this is the first draft so I have not written exactly what that means yet ...
And we probably need to do something more robust with capturing the data line to prevent noise from being an issue. Again, an exercise for later ...
The only way we get this far is if we are initialized, do not think it was noise and do not think it looked like [i.e. looked like, but could have been invalid] a 'beginning of burst' pulse.
First thing to do is to see if we are in the process of accepting a burst. If not, then things are not going well. I am assuming another punt.
The stream should be completed in [information from the scope goes here, but a relatively short time] microseconds so if it took longer than that we will again call the punter in.
Finally it seems like we actually have another bit of data to capture. Shift the captured stream to the left one bit, capture the data line [see previous comment about noisy data] and increment the bit count.
It is possible that we've now received all of the bits [information from the scope goes here to determine how many bits we need] in the stream. If so then move the interim stream to somewhere an outside processes can easily get to it, increment a byte counter so the outside process knows a new stream is available and set things up so we are ready to go if we ever see another 'start of burst' condition.
The thought is that the interrupt routine will capture the stream of bits in a burst into an unsigned long. The interrupt will not try to figure out what the bits mean. That is the job of the application loop ... to take a completed burst and figure out what the bit pattern means based on the scale protocol.
Note that we don't care ... other than the value in the define ... if the transitions a rising or falling. All we are concerned about is that when a transition happens we are led to believe that the information on the data line is 'valid'.
The first thing we do on a transition is determine the time of the interrupt and how long it has been since the last interrupt. They are both unsigned so we do not need to worry about things like rollover. We do this for all interrupts as only the very first interrupt we see does not care about the interval so lets make life simple.
Code:
void clockTransitioned() {
unsigned long timeAtInterupt = micros();
unsigned long intervalSinceLastInterrupt = timeAtInterupt - lastGoodClockTime;
The next thing we need to do is determine if this is the very first interrupt we have seen since we started the application. If it is the first one we have no idea where were are at with the clock so even our 'last time' does not have meaning and therefore our interval does not have meaning. Lets capture the time and set a couple of "here is where we are" sticks in the ground so we are be ready for the next interrupt.
Code:
// If we do not have our ducks in a row so we will get organized
if (!initialized) {
lastGoodClockTime = timeAtInterupt;
processingBurst = false;
initialized = true;
}
All of the following interrupts fall thru to the next if. Now that we have a valid 'last time' and therefore a valid 'interval' we can see how long it has been since the last interrupt. If the interval is 'too soon' [we need to look at what we get from the scope to determine some of these values] then we consider it noise and just ignore it.
Code:
// Is the interrupt because of noise?
else if (intervalSinceLastInterrupt < CLOCK_NOISE_FILTER) {
/*
Note that we are going to do absolutely nothing in this case, not even update the last valid clock time.
We are really waiting for a transition that is at least CLOCK_NOISE_FILTER later than the
last transition that we thought was good.
*/
}
If it is not noise then maybe it is the beginning of a burst. We identify the beginning of a burst as having been [information from the scope goes here, but a relatively long time] microseconds since the last interrupt. If we think it is the beginning of the burst then do some things to start capturing the bit stream and that's it.
There is the possibility that we find what we think is the beginning of a burst while we are processing a burst. We will punt but this is the first draft so I have not written exactly what that means yet ...
And we probably need to do something more robust with capturing the data line to prevent noise from being an issue. Again, an exercise for later ...
Code:
// Is the interrupt because of a 'beginning of burst' pulse?
else if (intervalSinceLastInterrupt > MINIMUM_BURST_START_PULSE_WIDTH) {
if (!processingBurst) {
lastGoodClockTime = timeAtInterupt;
burstStartTime = timeAtInterupt;
inProcessBurstData = digitalRead(DATA_PIN);
dataBitsReceived = 1;
processingBurst = true;
}
// OK, we were in the process of receiving a burst but just got another 'beginning of burst' pulse.
// We'll need to do something here but I will have to figure out exactly what after another cup of coffee.
else {
}
The only way we get this far is if we are initialized, do not think it was noise and do not think it looked like [i.e. looked like, but could have been invalid] a 'beginning of burst' pulse.
First thing to do is to see if we are in the process of accepting a burst. If not, then things are not going well. I am assuming another punt.
Code:
else {
// If we are not in the process of reading a burst then we have a problem and need more coffee
if (!processingBurst) {
}
The stream should be completed in [information from the scope goes here, but a relatively short time] microseconds so if it took longer than that we will again call the punter in.
Code:
// If it has taken longer than we thought is should to show up then we have a problem ... see the coffe issue mentined earlier
else if ((timeAtInterupt - burstStartTime) > MAXIMUM_TIME_FOR_A_SINGLE_BURST) {
}
Finally it seems like we actually have another bit of data to capture. Shift the captured stream to the left one bit, capture the data line [see previous comment about noisy data] and increment the bit count.
Code:
// We seem to be at the right place at the right time so grab what ever is on the data line.
else {
lastGoodClockTime = timeAtInterupt;
inProcessBurstData << 1; // Make room for the next data bit
inProcessBurstData | digitalRead(DATA_PIN); // and then capture it
dataBitsReceived += 1;
It is possible that we've now received all of the bits [information from the scope goes here to determine how many bits we need] in the stream. If so then move the interim stream to somewhere an outside processes can easily get to it, increment a byte counter so the outside process knows a new stream is available and set things up so we are ready to go if we ever see another 'start of burst' condition.
Code:
if (dataBitsReceived == DATA_BITS_IN_A_VALID_BURST) { // Are we done with this burst?
capturedBurstData = inProcessBurstData;
capturedBurstCounter ++;
processingBurst = false;
}
}
}
}