This CRC6 snippet gives wrong results The Next CEO of Stack OverflowDo I cast the result of malloc?Pseudo code for instruction descriptionWhy is “while (!feof(file))” always wrong?CRC programming help needed, CRC32 conversion from the .NET class to CArduino CRC32 Code Explanation searchedHow to configure calculation of CRC tableBasic CRC32 Wikipedia implementation differs from standard CRC32 seen onlineCRC32 calculation with CRC hash at the beginning of the message in CP1 Meter CRC16 checksumCRC-15 giving wrong values

India just shot down a satellite from the ground. At what altitude range is the resulting debris field?

Term for the "extreme-extension" version of a straw man fallacy?

How to count occurrences of text in a file?

Whats the best way to handle refactoring a big file?

Why didn't Theresa May consult with Parliament before negotiating a deal with the EU?

What is the purpose of the Evocation wizard's Potent Cantrip feature?

If I blow insulation everywhere in my attic except the door trap, will heat escape through it?

How did people program for Consoles with multiple CPUs?

Which organization defines CJK Unified Ideographs?

Why didn't Khan get resurrected in the Genesis Explosion?

Need some help with wall behind rangetop

Apart from "berlinern", do any other German dialects have a corresponding verb?

Opposite of a diet

Trouble understanding the speech of overseas colleagues

How do I go from 300 unfinished/half written blog posts, to published posts?

Anatomically Correct Strange Women In Ponds Distributing Swords

Why does C# sound extremely flat when saxophone is tuned to G?

How do spells that require an ability check vs. the caster's spell save DC work?

How to understand which control sequence in undefined in "Undefined control sequence." message?

Can the Reverse Gravity spell affect the Meteor Swarm spell?

How to write papers efficiently when English isn't my first language?

The King's new dress

How to write the block matrix in LaTex?

Would this house-rule that treats advantage as a +1 to the roll instead (and disadvantage as -1) and allows them to stack be balanced?



This CRC6 snippet gives wrong results



The Next CEO of Stack OverflowDo I cast the result of malloc?Pseudo code for instruction descriptionWhy is “while (!feof(file))” always wrong?CRC programming help needed, CRC32 conversion from the .NET class to CArduino CRC32 Code Explanation searchedHow to configure calculation of CRC tableBasic CRC32 Wikipedia implementation differs from standard CRC32 seen onlineCRC32 calculation with CRC hash at the beginning of the message in CP1 Meter CRC16 checksumCRC-15 giving wrong values










2















A code snippet to generate CRC6 is not giving the right value.
What could be the problem in the code snippet?



SPI_CRC6 = X6 + X4 + X3 + X + 1


The initial seed value is 0x3F

Input data: 24 bit.



A few tested sample values:(not from code snippet)



24b input: 0xAE0000, CRC6: 0x11
24b input: 0x950055, CRC6: 0x22




/* CRC6 calculation */
Uint16 crc2(Uint32 datin)

Uint16 byte_idx, bit_idx, crc = (0x3F << 2);//CRC_INITSEED = 0x3f

/* byte by byte starting from most significant (3-2-1) */
for (byte_idx = 3; byte_idx >= 1; byte_idx--)

/* XOR-in new byte from left to right */
crc ^= ((datin >> (byte_idx << 3)) & 0x000000FF);

/* bit by bit for each byte */
for (bit_idx = 0; bit_idx < 8; bit_idx++)

crc = crc << 1 ^ (crc & 0x80 ? (0x5B << 2) : 0);//CRC Polynom: 0x5B



return (crc >> 2 & 0x3F); /*restore two bit offset */










share|improve this question



















  • 1





    The code needs to right shift in multiples of 6 bits (18, 12, 6, 0). It would be simpler if you kept the CRC in the lower 6 bits of crc.

    – rcgldr
    Mar 8 at 20:26















2















A code snippet to generate CRC6 is not giving the right value.
What could be the problem in the code snippet?



SPI_CRC6 = X6 + X4 + X3 + X + 1


The initial seed value is 0x3F

Input data: 24 bit.



A few tested sample values:(not from code snippet)



24b input: 0xAE0000, CRC6: 0x11
24b input: 0x950055, CRC6: 0x22




/* CRC6 calculation */
Uint16 crc2(Uint32 datin)

Uint16 byte_idx, bit_idx, crc = (0x3F << 2);//CRC_INITSEED = 0x3f

/* byte by byte starting from most significant (3-2-1) */
for (byte_idx = 3; byte_idx >= 1; byte_idx--)

/* XOR-in new byte from left to right */
crc ^= ((datin >> (byte_idx << 3)) & 0x000000FF);

/* bit by bit for each byte */
for (bit_idx = 0; bit_idx < 8; bit_idx++)

crc = crc << 1 ^ (crc & 0x80 ? (0x5B << 2) : 0);//CRC Polynom: 0x5B



return (crc >> 2 & 0x3F); /*restore two bit offset */










share|improve this question



















  • 1





    The code needs to right shift in multiples of 6 bits (18, 12, 6, 0). It would be simpler if you kept the CRC in the lower 6 bits of crc.

    – rcgldr
    Mar 8 at 20:26













2












2








2








A code snippet to generate CRC6 is not giving the right value.
What could be the problem in the code snippet?



SPI_CRC6 = X6 + X4 + X3 + X + 1


The initial seed value is 0x3F

Input data: 24 bit.



A few tested sample values:(not from code snippet)



24b input: 0xAE0000, CRC6: 0x11
24b input: 0x950055, CRC6: 0x22




/* CRC6 calculation */
Uint16 crc2(Uint32 datin)

Uint16 byte_idx, bit_idx, crc = (0x3F << 2);//CRC_INITSEED = 0x3f

/* byte by byte starting from most significant (3-2-1) */
for (byte_idx = 3; byte_idx >= 1; byte_idx--)

/* XOR-in new byte from left to right */
crc ^= ((datin >> (byte_idx << 3)) & 0x000000FF);

/* bit by bit for each byte */
for (bit_idx = 0; bit_idx < 8; bit_idx++)

crc = crc << 1 ^ (crc & 0x80 ? (0x5B << 2) : 0);//CRC Polynom: 0x5B



return (crc >> 2 & 0x3F); /*restore two bit offset */










share|improve this question
















A code snippet to generate CRC6 is not giving the right value.
What could be the problem in the code snippet?



SPI_CRC6 = X6 + X4 + X3 + X + 1


The initial seed value is 0x3F

Input data: 24 bit.



A few tested sample values:(not from code snippet)



24b input: 0xAE0000, CRC6: 0x11
24b input: 0x950055, CRC6: 0x22




/* CRC6 calculation */
Uint16 crc2(Uint32 datin)

Uint16 byte_idx, bit_idx, crc = (0x3F << 2);//CRC_INITSEED = 0x3f

/* byte by byte starting from most significant (3-2-1) */
for (byte_idx = 3; byte_idx >= 1; byte_idx--)

/* XOR-in new byte from left to right */
crc ^= ((datin >> (byte_idx << 3)) & 0x000000FF);

/* bit by bit for each byte */
for (bit_idx = 0; bit_idx < 8; bit_idx++)

crc = crc << 1 ^ (crc & 0x80 ? (0x5B << 2) : 0);//CRC Polynom: 0x5B



return (crc >> 2 & 0x3F); /*restore two bit offset */







c crc






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Mar 8 at 13:13









Zeta

83.1k11143194




83.1k11143194










asked Mar 8 at 13:09









AAHAAH

111




111







  • 1





    The code needs to right shift in multiples of 6 bits (18, 12, 6, 0). It would be simpler if you kept the CRC in the lower 6 bits of crc.

    – rcgldr
    Mar 8 at 20:26












  • 1





    The code needs to right shift in multiples of 6 bits (18, 12, 6, 0). It would be simpler if you kept the CRC in the lower 6 bits of crc.

    – rcgldr
    Mar 8 at 20:26







1




1





The code needs to right shift in multiples of 6 bits (18, 12, 6, 0). It would be simpler if you kept the CRC in the lower 6 bits of crc.

– rcgldr
Mar 8 at 20:26





The code needs to right shift in multiples of 6 bits (18, 12, 6, 0). It would be simpler if you kept the CRC in the lower 6 bits of crc.

– rcgldr
Mar 8 at 20:26












2 Answers
2






active

oldest

votes


















0














The code shifts the input by 24,16,8 bits when it should be shifting by 16,8,0 bits. One way to fix that (and simplify the code at the same time) is to use the shift count as the loop parameter.



The code is also processing the input 8 bits at a time. This results in mysterious shifts by 2 throughout the code. It's much more natural to process 6 bits at a time. In that case the code needs to shift the input by 18,12,6,0 bits.



So I would write the code like this:



/* CRC6 calculation */
Uint16 crc2(Uint32 datin)

int input_shift;
Uint16 bit_idx, crc = 0x3F; //CRC seed = 0x3F

/* 6 bits at a time starting from most significant */
for (input_shift = 18; input_shift >= 0; input_shift -= 6)

/* XOR-in new data from left to right */
crc ^= (datin >> input_shift) & 0x3F;

/* bit by bit for each chunk */
for (bit_idx = 0; bit_idx < 6; bit_idx++)

crc <<= 1;
crc ^= (crc & 0x40) ? 0x5B : 0; //CRC polynomial: 0x5B



return crc & 0x3F; //return the 6-bit CRC






share|improve this answer






























    0














    user3386109's answer shows a corrected version of your code, but in this case, there's no need to split up datain into 6 bit fields.



    typedef unsigned short uint16_t;
    typedef unsigned int uint32_t;

    uint16_t crc1(uint32_t datin)

    int i;
    uint32_t crc = datin ^ (0x3f << 18);
    for (i = 0; i < 24; i++)
    crc = (crc << 1) ^ ((crc & 0x800000) ? (0x5B << 18) : 0);
    return crc >> 18;



    The following example assumes two's complement math, using (-0) = 0x00000000 or (-1) = 0xffffffff as a mask to avoid using conditional code (tenary ? : ). Note that an optimizing compiler may use math to avoid conditional code for the above example as well (Visual Studio does this).



    typedef unsigned short uint16_t;
    typedef unsigned int uint32_t;

    uint16_t crc1(uint32_t datin)

    int i;
    uint32_t crc = datin ^ (0x3f << 18);
    for (i = 0; i < 24; i++)
    crc = (crc << 1) ^ ((-(crc >> 23)) & (0x5B << 18));
    return crc >> 18;



    The masking trick is often used by compilers, the general sequence is:



     ... ;eax is zero or non-zero
    neg eax ;sets borrow bit if eax != 0
    sbb eax,eax ;eax = 0x00000000 or 0xffffffff
    and eax,... ;use eax as mask





    share|improve this answer

























      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55063905%2fthis-crc6-snippet-gives-wrong-results%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      0














      The code shifts the input by 24,16,8 bits when it should be shifting by 16,8,0 bits. One way to fix that (and simplify the code at the same time) is to use the shift count as the loop parameter.



      The code is also processing the input 8 bits at a time. This results in mysterious shifts by 2 throughout the code. It's much more natural to process 6 bits at a time. In that case the code needs to shift the input by 18,12,6,0 bits.



      So I would write the code like this:



      /* CRC6 calculation */
      Uint16 crc2(Uint32 datin)

      int input_shift;
      Uint16 bit_idx, crc = 0x3F; //CRC seed = 0x3F

      /* 6 bits at a time starting from most significant */
      for (input_shift = 18; input_shift >= 0; input_shift -= 6)

      /* XOR-in new data from left to right */
      crc ^= (datin >> input_shift) & 0x3F;

      /* bit by bit for each chunk */
      for (bit_idx = 0; bit_idx < 6; bit_idx++)

      crc <<= 1;
      crc ^= (crc & 0x40) ? 0x5B : 0; //CRC polynomial: 0x5B



      return crc & 0x3F; //return the 6-bit CRC






      share|improve this answer



























        0














        The code shifts the input by 24,16,8 bits when it should be shifting by 16,8,0 bits. One way to fix that (and simplify the code at the same time) is to use the shift count as the loop parameter.



        The code is also processing the input 8 bits at a time. This results in mysterious shifts by 2 throughout the code. It's much more natural to process 6 bits at a time. In that case the code needs to shift the input by 18,12,6,0 bits.



        So I would write the code like this:



        /* CRC6 calculation */
        Uint16 crc2(Uint32 datin)

        int input_shift;
        Uint16 bit_idx, crc = 0x3F; //CRC seed = 0x3F

        /* 6 bits at a time starting from most significant */
        for (input_shift = 18; input_shift >= 0; input_shift -= 6)

        /* XOR-in new data from left to right */
        crc ^= (datin >> input_shift) & 0x3F;

        /* bit by bit for each chunk */
        for (bit_idx = 0; bit_idx < 6; bit_idx++)

        crc <<= 1;
        crc ^= (crc & 0x40) ? 0x5B : 0; //CRC polynomial: 0x5B



        return crc & 0x3F; //return the 6-bit CRC






        share|improve this answer

























          0












          0








          0







          The code shifts the input by 24,16,8 bits when it should be shifting by 16,8,0 bits. One way to fix that (and simplify the code at the same time) is to use the shift count as the loop parameter.



          The code is also processing the input 8 bits at a time. This results in mysterious shifts by 2 throughout the code. It's much more natural to process 6 bits at a time. In that case the code needs to shift the input by 18,12,6,0 bits.



          So I would write the code like this:



          /* CRC6 calculation */
          Uint16 crc2(Uint32 datin)

          int input_shift;
          Uint16 bit_idx, crc = 0x3F; //CRC seed = 0x3F

          /* 6 bits at a time starting from most significant */
          for (input_shift = 18; input_shift >= 0; input_shift -= 6)

          /* XOR-in new data from left to right */
          crc ^= (datin >> input_shift) & 0x3F;

          /* bit by bit for each chunk */
          for (bit_idx = 0; bit_idx < 6; bit_idx++)

          crc <<= 1;
          crc ^= (crc & 0x40) ? 0x5B : 0; //CRC polynomial: 0x5B



          return crc & 0x3F; //return the 6-bit CRC






          share|improve this answer













          The code shifts the input by 24,16,8 bits when it should be shifting by 16,8,0 bits. One way to fix that (and simplify the code at the same time) is to use the shift count as the loop parameter.



          The code is also processing the input 8 bits at a time. This results in mysterious shifts by 2 throughout the code. It's much more natural to process 6 bits at a time. In that case the code needs to shift the input by 18,12,6,0 bits.



          So I would write the code like this:



          /* CRC6 calculation */
          Uint16 crc2(Uint32 datin)

          int input_shift;
          Uint16 bit_idx, crc = 0x3F; //CRC seed = 0x3F

          /* 6 bits at a time starting from most significant */
          for (input_shift = 18; input_shift >= 0; input_shift -= 6)

          /* XOR-in new data from left to right */
          crc ^= (datin >> input_shift) & 0x3F;

          /* bit by bit for each chunk */
          for (bit_idx = 0; bit_idx < 6; bit_idx++)

          crc <<= 1;
          crc ^= (crc & 0x40) ? 0x5B : 0; //CRC polynomial: 0x5B



          return crc & 0x3F; //return the 6-bit CRC







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Mar 8 at 22:11









          user3386109user3386109

          28.3k53348




          28.3k53348























              0














              user3386109's answer shows a corrected version of your code, but in this case, there's no need to split up datain into 6 bit fields.



              typedef unsigned short uint16_t;
              typedef unsigned int uint32_t;

              uint16_t crc1(uint32_t datin)

              int i;
              uint32_t crc = datin ^ (0x3f << 18);
              for (i = 0; i < 24; i++)
              crc = (crc << 1) ^ ((crc & 0x800000) ? (0x5B << 18) : 0);
              return crc >> 18;



              The following example assumes two's complement math, using (-0) = 0x00000000 or (-1) = 0xffffffff as a mask to avoid using conditional code (tenary ? : ). Note that an optimizing compiler may use math to avoid conditional code for the above example as well (Visual Studio does this).



              typedef unsigned short uint16_t;
              typedef unsigned int uint32_t;

              uint16_t crc1(uint32_t datin)

              int i;
              uint32_t crc = datin ^ (0x3f << 18);
              for (i = 0; i < 24; i++)
              crc = (crc << 1) ^ ((-(crc >> 23)) & (0x5B << 18));
              return crc >> 18;



              The masking trick is often used by compilers, the general sequence is:



               ... ;eax is zero or non-zero
              neg eax ;sets borrow bit if eax != 0
              sbb eax,eax ;eax = 0x00000000 or 0xffffffff
              and eax,... ;use eax as mask





              share|improve this answer





























                0














                user3386109's answer shows a corrected version of your code, but in this case, there's no need to split up datain into 6 bit fields.



                typedef unsigned short uint16_t;
                typedef unsigned int uint32_t;

                uint16_t crc1(uint32_t datin)

                int i;
                uint32_t crc = datin ^ (0x3f << 18);
                for (i = 0; i < 24; i++)
                crc = (crc << 1) ^ ((crc & 0x800000) ? (0x5B << 18) : 0);
                return crc >> 18;



                The following example assumes two's complement math, using (-0) = 0x00000000 or (-1) = 0xffffffff as a mask to avoid using conditional code (tenary ? : ). Note that an optimizing compiler may use math to avoid conditional code for the above example as well (Visual Studio does this).



                typedef unsigned short uint16_t;
                typedef unsigned int uint32_t;

                uint16_t crc1(uint32_t datin)

                int i;
                uint32_t crc = datin ^ (0x3f << 18);
                for (i = 0; i < 24; i++)
                crc = (crc << 1) ^ ((-(crc >> 23)) & (0x5B << 18));
                return crc >> 18;



                The masking trick is often used by compilers, the general sequence is:



                 ... ;eax is zero or non-zero
                neg eax ;sets borrow bit if eax != 0
                sbb eax,eax ;eax = 0x00000000 or 0xffffffff
                and eax,... ;use eax as mask





                share|improve this answer



























                  0












                  0








                  0







                  user3386109's answer shows a corrected version of your code, but in this case, there's no need to split up datain into 6 bit fields.



                  typedef unsigned short uint16_t;
                  typedef unsigned int uint32_t;

                  uint16_t crc1(uint32_t datin)

                  int i;
                  uint32_t crc = datin ^ (0x3f << 18);
                  for (i = 0; i < 24; i++)
                  crc = (crc << 1) ^ ((crc & 0x800000) ? (0x5B << 18) : 0);
                  return crc >> 18;



                  The following example assumes two's complement math, using (-0) = 0x00000000 or (-1) = 0xffffffff as a mask to avoid using conditional code (tenary ? : ). Note that an optimizing compiler may use math to avoid conditional code for the above example as well (Visual Studio does this).



                  typedef unsigned short uint16_t;
                  typedef unsigned int uint32_t;

                  uint16_t crc1(uint32_t datin)

                  int i;
                  uint32_t crc = datin ^ (0x3f << 18);
                  for (i = 0; i < 24; i++)
                  crc = (crc << 1) ^ ((-(crc >> 23)) & (0x5B << 18));
                  return crc >> 18;



                  The masking trick is often used by compilers, the general sequence is:



                   ... ;eax is zero or non-zero
                  neg eax ;sets borrow bit if eax != 0
                  sbb eax,eax ;eax = 0x00000000 or 0xffffffff
                  and eax,... ;use eax as mask





                  share|improve this answer















                  user3386109's answer shows a corrected version of your code, but in this case, there's no need to split up datain into 6 bit fields.



                  typedef unsigned short uint16_t;
                  typedef unsigned int uint32_t;

                  uint16_t crc1(uint32_t datin)

                  int i;
                  uint32_t crc = datin ^ (0x3f << 18);
                  for (i = 0; i < 24; i++)
                  crc = (crc << 1) ^ ((crc & 0x800000) ? (0x5B << 18) : 0);
                  return crc >> 18;



                  The following example assumes two's complement math, using (-0) = 0x00000000 or (-1) = 0xffffffff as a mask to avoid using conditional code (tenary ? : ). Note that an optimizing compiler may use math to avoid conditional code for the above example as well (Visual Studio does this).



                  typedef unsigned short uint16_t;
                  typedef unsigned int uint32_t;

                  uint16_t crc1(uint32_t datin)

                  int i;
                  uint32_t crc = datin ^ (0x3f << 18);
                  for (i = 0; i < 24; i++)
                  crc = (crc << 1) ^ ((-(crc >> 23)) & (0x5B << 18));
                  return crc >> 18;



                  The masking trick is often used by compilers, the general sequence is:



                   ... ;eax is zero or non-zero
                  neg eax ;sets borrow bit if eax != 0
                  sbb eax,eax ;eax = 0x00000000 or 0xffffffff
                  and eax,... ;use eax as mask






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Mar 9 at 3:31

























                  answered Mar 9 at 2:43









                  rcgldrrcgldr

                  15.9k31435




                  15.9k31435



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55063905%2fthis-crc6-snippet-gives-wrong-results%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Can't initialize raids on a new ASUS Prime B360M-A motherboard2019 Community Moderator ElectionSimilar to RAID config yet more like mirroring solution?Can't get motherboard serial numberWhy does the BIOS entry point start with a WBINVD instruction?UEFI performance Asus Maximus V Extreme

                      Identity Server 4 is not redirecting to Angular app after login2019 Community Moderator ElectionIdentity Server 4 and dockerIdentityserver implicit flow unauthorized_clientIdentityServer Hybrid Flow - Access Token is null after user successful loginIdentity Server to MVC client : Page Redirect After loginLogin with Steam OpenId(oidc-client-js)Identity Server 4+.NET Core 2.0 + IdentityIdentityServer4 post-login redirect not working in Edge browserCall to IdentityServer4 generates System.NullReferenceException: Object reference not set to an instance of an objectIdentityServer4 without HTTPS not workingHow to get Authorization code from identity server without login form

                      2005 Ahvaz unrest Contents Background Causes Casualties Aftermath See also References Navigation menue"At Least 10 Are Killed by Bombs in Iran""Iran"Archived"Arab-Iranians in Iran to make April 15 'Day of Fury'"State of Mind, State of Order: Reactions to Ethnic Unrest in the Islamic Republic of Iran.10.1111/j.1754-9469.2008.00028.x"Iran hangs Arab separatists"Iran Overview from ArchivedConstitution of the Islamic Republic of Iran"Tehran puzzled by forged 'riots' letter""Iran and its minorities: Down in the second class""Iran: Handling Of Ahvaz Unrest Could End With Televised Confessions""Bombings Rock Iran Ahead of Election""Five die in Iran ethnic clashes""Iran: Need for restraint as anniversary of unrest in Khuzestan approaches"Archived"Iranian Sunni protesters killed in clashes with security forces"Archived