Reading data at 10 Khz rate

So if it goes out of sync it recovers with the loss of no more than 3 frames of data. Is that acceptable to you or do you need to refine that further?

Hi guys I am back with another problem. If i want to read the data exactly on each rising edge using interrupt how to approach that way??? All other things mentioned earlier still remains same ( reading "CAAC1F" and match found read the next remaining 32 bytes of data). I have never written an ISR and pretty clueless how to set the proper register(currently i am going through the datasheet but without any background knowledge i am struggling a lot) Any help??? Thanks in advance Niladri

Hi Niladri

Can you share the code as you have it presently?

Geoff

Sorry this is the present code

const int CLOCK_PIN     =    2;
const int DATA_PIN      =    4;
const int PACKET_BITS   =    128;
const int PREAMBLE_LEN  =    6;
const int DATA_LEN      =    26;

enum {
    PRE_0,    PRE_1,    PRE_2,    PRE_3,    PRE_4,    PRE_5,    DATA
} states;    

byte     preamble [] = {0x0C,0x0A,0x0A,0x0C,0x01,0x0F};
char     hexAsciiVals[] = "0123456789ABCDEF";
byte     state = PRE_0;
byte     nibble;
int        nibble_count = 0;

void setup() {
  pinMode(CLOCK_PIN, INPUT);
  pinMode(DATA_PIN, INPUT);
  Serial.begin(115200);
}

void loop() {

    nibble = getNibble();
    nibble_count++;
    
//    Serial.print(digitalRead(CLOCK_PIN));
    
    switch (state) {    
        case PRE_0:
            if (nibble_count > 32) {
                // we've read 32 bytes and still not found a match 
                // for the preamble so skip a clock pulse
                while (digitalRead(CLOCK_PIN) == LOW);
                while (digitalRead(CLOCK_PIN) == HIGH);
                nibble_count = 0;
            } 
            else 
            {
                if(nibble == preamble[0]) 
                      state = PRE_1;
                else
                      state = PRE_0;
            }
            break;
            
        case PRE_1:
            if(nibble == preamble[1]) 
                 state = PRE_2;
            else
                 state = PRE_0;    
            break;
            
        case PRE_2:
            if(nibble == preamble[2]) 
                state = PRE_3;
            else
                state = PRE_0;
            break;
            
        case PRE_3:
            if(nibble == preamble[3]) 
               state = PRE_4;
            else
               state = PRE_0;
            break;
            
        case PRE_4:
            if(nibble == preamble[4]) 
              state = PRE_5;
            else
              state = PRE_0;
            break;
            
        case PRE_5:
            if(nibble == preamble[5])
             state = DATA;
            else
             state = PRE_0;
            break;
            
        case DATA:
            Serial.print (hexAsciiVals[nibble]);
            if (nibble_count == DATA_LEN) {
                // all done, start again
                state = PRE_0;
                nibble_count = 0;
                Serial.println();
            }
            break;
    }
}

byte getNibble() {

    byte val = 0;
    
    for (byte bit_count = 0; bit_count < 4; bit_count++) {
        while (digitalRead(CLOCK_PIN) == HIGH);
        
          while (digitalRead(CLOCK_PIN) == LOW);
          val <<= 1;
          val |= digitalRead(DATA_PIN);
        }
    return (val &= 0x0F);
}

Finally it’s working thanks everyone for their help and support without your help it would not been possible and i am posting the working code if in case anyone wants to refer it for their future use…
Thanks…

const int CLOCK_PIN     =     2;
const int DATA_PIN      =     4;
const int PACKET_BITS   =     256;
const int PREAMBLE_LEN  =     6;
const int DATA_LEN      =     ((PACKET_BITS / 4) - PREAMBLE_LEN);

enum {
    PRE_0,    PRE_1,    PRE_2,    PRE_3,    PRE_4,    PRE_5,    DATA
} states;    

byte     preamble [] = {0x0C,0x0A,0x0A,0x0C,0x01,0x0F};
char     hexAsciiVals[] = "0123456789ABCDEF";
byte     state = PRE_0;
byte     nibble;
int      nibble_count = 0;
byte     firstval;

void setup() {
  pinMode(CLOCK_PIN, INPUT);
  pinMode(DATA_PIN, INPUT);
  Serial.begin(9600);
}

void loop() {

    nibble = getNibble();
    //nibble_count++;
    
    
    switch (state) {    
        case PRE_0:
//            if (nibble_count > PREAMBLE_LEN + DATA_LEN) {
//                // we've read 32 bytes and still not found a match 
//                // for the preamble so skip a clock pulse
//                while (digitalRead(CLOCK_PIN) == LOW);
//                while (digitalRead(CLOCK_PIN) == HIGH);
//                nibble_count = 0;
//            } else 
//            {
//                firstval = 12;
//                Serial.write(hexAsciiVals[firstval]);
                
                state = (nibble == preamble[0]) ? PRE_1 : PRE_0;
              //  Serial.write(hexAsciiVals[nibble]);
//            }
            break;
        
        case PRE_1:
            
           // Serial.write (hexAsciiVals[firstval]);
           // Serial.print(hexAsciiVals[12]);
            Serial.print(hexAsciiVals[nibble]);
            state = (nibble == preamble[1]) ? PRE_2 : PRE_0;    
            //Serial.write (hexAsciiVals[nibble]);
            break;
            
        case PRE_2:
            Serial.print(hexAsciiVals[nibble]);
            state = (nibble == preamble[2]) ? PRE_3 : PRE_0;
            //Serial.write (hexAsciiVals[nibble]);
            break;

        case PRE_3:
            Serial.print(hexAsciiVals[nibble]);
            state = (nibble == preamble[3]) ? PRE_4 : PRE_0;
            //Serial.write (hexAsciiVals[nibble]);
            break;

        case PRE_4:
            Serial.print(hexAsciiVals[nibble]);
            state = (nibble == preamble[4]) ? PRE_5 : PRE_0;
            //Serial.write (hexAsciiVals[nibble]);
            break;
        
        case PRE_5:
            Serial.print(hexAsciiVals[nibble]);
            state = (nibble == preamble[5]) ? DATA : PRE_0;
            //Serial.write (hexAsciiVals[nibble]);
            //   nibble_count = 0;
            break;
            
        case DATA:
           
            Serial.print(hexAsciiVals[nibble]);
            if (nibble_count == DATA_LEN) {
                // all done, start again
                state = PRE_0;
                nibble_count = 0;
                Serial.println(' ');
                Serial.print(hexAsciiVals[12]);
                
            }
            
            nibble_count++;
            //Serial.println();
            break;
    }
    
  //  delay(10);
}

byte getNibble() {

    byte val = 0;
    
    for (byte bit_count = 0; bit_count < 4; bit_count++) {
        while (digitalRead(CLOCK_PIN) == HIGH);
        while (digitalRead(CLOCK_PIN) == LOW);
        val <<= 1;
        val |= digitalRead(DATA_PIN); 
    }
    return (val &= 0x0F);
}

Just for curiosity i tried to read byte by byte rather than nibble by nibble but it does not read the data at all. Can anybody indicate where i am doing wrong.

const int CLOCK_PIN     =     2;
const int DATA_PIN      =     4;
const int PACKET_BITS   =     1024;
const int PREAMBLE_LEN  =     3;
const int DATA_LEN      =     ((PACKET_BITS / 8) - PREAMBLE_LEN);

enum {
    PRE_0,    PRE_1,    PRE_2,    PRE_3,    PRE_4,    PRE_5,    DATA
} states;    

byte     preamble [] = {0xCA,0xAC,0x1F};
char     hexAsciiVals[] = "0123456789ABCDEF0123456789ABCDEF";
byte     state = PRE_0;
byte     nibble;
int      nibble_count = 0;
byte     firstval;
//const char  header = "CAAC1F";

void setup() {
  pinMode(CLOCK_PIN, INPUT);
  pinMode(DATA_PIN, INPUT);
  Serial.begin(57600);
}

void loop() {

    nibble = getNibble();
    //nibble_count++;
    
    
    switch (state) {    
        case PRE_0:
//            if (nibble_count > PREAMBLE_LEN + DATA_LEN) {
//                // we've read 32 bytes and still not found a match 
//                // for the preamble so skip a clock pulse
//                while (digitalRead(CLOCK_PIN) == LOW);
//                while (digitalRead(CLOCK_PIN) == HIGH);
//                nibble_count = 0;
//            } else 
//            {
//                firstval = 12;
//                Serial.write(hexAsciiVals[firstval]);
                
                state = (nibble == preamble[0]) ? PRE_1 : PRE_0;
              //  Serial.write(hexAsciiVals[nibble]);
//            }
            break;
        
        case PRE_1:
            
           // Serial.write (hexAsciiVals[firstval]);
           // Serial.print(hexAsciiVals[12]);
           // Serial.print(hexAsciiVals[nibble]);
            state = (nibble == preamble[1]) ? PRE_2 : PRE_0;    
            //Serial.write (hexAsciiVals[nibble]);
            break;
            
        case PRE_2:
          //  Serial.print(hexAsciiVals[nibble]);
            state = (nibble == preamble[2]) ? DATA : PRE_0;
            //Serial.write (hexAsciiVals[nibble]);
            break;

//        case PRE_3:
//          //  Serial.print(hexAsciiVals[nibble]);
//            state = (nibble == preamble[3]) ? PRE_4 : PRE_0;
//        //    Serial.write (hexAsciiVals[nibble]);
//            break;
//
//        case PRE_4:
//           // Serial.print(hexAsciiVals[nibble]);
//            state = (nibble == preamble[4]) ? PRE_5 : PRE_0;
//           // Serial.write (hexAsciiVals[nibble]);
//            break;
//        
//        case PRE_5:
//           // Serial.print(hexAsciiVals[nibble]);
//    //        Serial.print(202, HEX);
//  //          Serial.print(172, HEX);
//        //    Serial.println();
//            state = (nibble == preamble[5]) ? DATA : PRE_0;
//            Serial.print("$");
//            //   nibble_count = 0;
//            break;
            
        case DATA:
           //   Serial.print("CAAC1F");
            Serial.print(nibble, HEX);
            if (nibble_count == DATA_LEN) {
                // all done, start again
                state = PRE_0;
                nibble_count = 0;
             //   Serial.print("\n");
           //     Serial.print(hexAsciiVals[12]);
                
            }
            
            nibble_count++;
            //Serial.println();
            break;
    }
    
  //  delay(10);
}

byte getNibble() {

    byte val = 0;
    
    for (byte bit_count = 0; bit_count < 8; bit_count++) {
        while (digitalRead(CLOCK_PIN) == HIGH);
        while (digitalRead(CLOCK_PIN) == LOW);
        val <<= 1;
        val |= digitalRead(DATA_PIN); 
    }
    return (val &= 0xFF);
}

Hi,

This thread takes me back :)

Rob's state machine was based on testing the 4 bit nibbles, so you'd have to rewrite that too, not just the getNibble() function. I'd be concerned though that while the previous logic could be out of sync with the stream by up to 3 bits, this could get lost by up to 7. This would lead to potentially more than double the data loss on those occasions while the sketch found the correct preamble again.

Why would you want to do it byte by byte? Didn't you have this working as at your previous post?

Geoff

No it is working fine and there no necessity for me make it 8 bit but for just better understanding that if the state machine works for 4 bit then if we do slight modification on the state machine it should work for 8 bit. So i modified the state machine as well as getNibble() function but it does not read any data so i came to forum for possible solution(I am work alone so i have no other alternative). :)

Okay,

So for the sake of the exercise then :)

Can I ask why have you commented out the block at the start of case PRE_0: ? Without it surely if you start out of sync there's no way it can recover, so it could read the entire stream without ever discovering a valid preamble therefore will never find you any data.

Geoff

That's true but i need to shift bit by bit until i find a match so skipping a clock might not be best method as the data might be the particular preamble first bit(the preamble can be anywhere i don't where it starts so shift bit by bit 1st until match found).

Skipping a clock is just ignoring the next one bit so the next frame is read from 1 bit to the right in alignment down the stream. It’s only done when there’s been a full frame length read without finding a preamble (which means it’s out of sync and always would be).

Where is your code for returning to alignment if you’re not doing that?