Repository: Nicoretti/crc

Issue:
🔧 Refactor CRC-16 Configuration Naming and Expand Variants
# Summary
The current `Crc16.CCITT` implementation in our library aligns with `CRC-16/XMODEM`. Considering that "CCITT" refers to a group of related configurations rather than a single, specific one, utilizing "CCITT" for a distinct configuration is misleading. We propose removing the "CCITT" label and introducing all named variations under the CCITT umbrella to enhance clarity for users.

# Details

- Rename `Crc16.CCITT` to `Crc16.XMODEM` to accurately represent its configuration.
- Introduce additional predefined CRC-16 configurations, such as `Crc16.KERMIT`

## References
- #145 

# Task(s):
- [ ] Assess all predefined CRC-16 configurations in the library for accuracy in naming and parameters.
- [ ] Implement the renaming of `Crc16.CCITT` to `Crc16.XMODEM`.
- [ ] Add new CRC-16 configurations with accurate naming and parameters.
- [ ] Revise the documentation to reflect these changes, ensuring clarity and accessibility.
- [ ] Create tests for the new CRC-16 configurations to verify their correctness.
- [ ] Announce the refactoring in the changelog, including a brief explanation for the renaming and the addition of new configurations.

Expected Outcome:
The library will accurately represent various CRC-16 configurations, reducing confusion and increasing usability.


Discussion:
Nicoretti: Hi @IsaacDynamo and @cmcqueen,

you may want to have a look at this, once merged I will publish this as part of the `7.0.0` release.

best
Nico
cmcqueen: Looks good, thanks!

Patch:
diff --git a/README.md b/README.md
index 13b1cd3..860a3cb 100644
--- a/README.md
+++ b/README.md
@@ -34,13 +34,14 @@ Calculate CRC checksums, verify CRC checksum, predefined CRC configurations, cus
 ## Available CRC Configurations
 For convenience various frequently used crc configurations ship with the library out of the box.
 
-| CRC8 | CRC16    | CRC32 | CRC64 |
-|------|----------|-------|-------|
-| CCITT | CCITT    | CRC32 | CRC64 |
-| AUTOSAR | GSM      | AUTOSAR | |
-| SAEJ1850 | PROFIBUS | BZIP2 | |
-| BLUETOOTH | MODBUS   | POSIX | |
-| MAXIM-DOW | IBM-3740 | | | |
+| CRC8          | CRC16    | CRC32   | CRC64 |
+|---------------|----------|---------|-------|
+| CCITT         | XMODEM   | CRC32   | CRC64 |
+| AUTOSAR       | GSM      | AUTOSAR |       |
+| SAEJ1850      | PROFIBUS | BZIP2   |       |
+| SAEJ1850_ZERO | MODBUS   | POSIX   |       |
+| BLUETOOTH     | IBM-3740 |         |       |
+| MAXIM-DOW     | KERMIT   |         |       | 
 
 If you find yourself in the position, where having a new configuration available out of the
 box would be desirable, feel free to create a [PR](https://github.com/Nicoretti/crc/pulls) or file an [issue](https://github.com/Nicoretti/crc/issues).
diff --git a/docs/docs/changelog/unreleased.md b/docs/docs/changelog/unreleased.md
index 1622cea..f3a82e4 100644
--- a/docs/docs/changelog/unreleased.md
+++ b/docs/docs/changelog/unreleased.md
@@ -1,5 +1,29 @@
 # Unreleased
 
+## 🚨 Breaking Changes
+
+### Update of crc configurations
+- **Rename:** The `Crc16.CCITT` configuration to `Crc16.XMODEM`.
+- **New Addition:** Introduced `Crc16.KERMIT`, which matches the official configuration for `Crc16.CCITT`.
+
+#### Decision Rationale
+It was intentionally decided not to reintroduce `Crc16.CCITT` with the updated configuration. While it could have been added as an alias for `Crc16.KERMIT` or a replacement, omitting `Crc16.CCITT` ensures that client code will break upon update, thereby forcing maintainers to take notice and react accordingly.
+
+#### Migration Guide
+Below are solutions to the two common scenarios that need to be addressed due to this change:
+
+1. **If you previously used `Crc16.CCITT` and expected the configuration defined [here](https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.cat.crc-16-kermit):**
+
+      **Solution:** Replace all usages of `Crc16.CCITT` in your code with `Crc16.KERMIT`.
+
+2. **If you depended on or wanted to use the configuration values that `Crc16.CCITT` provided so far:**
+
+      **Solution:** Replace all usages of `Crc16.CCITT` in your code with `Crc16.XMODEM`.
+
+#### Related Issues
+- [#148](https://github.com/Nicoretti/crc/issues/148)
+- [#145](https://github.com/Nicoretti/crc/issues/145)
+
 ## 🔩  Internal
 * Update `python-environment` action
 * Add classifiers to `pyproject.toml`
diff --git a/docs/scripts/configurations.py b/docs/scripts/configurations.py
index f1316b6..4d4715b 100644
--- a/docs/scripts/configurations.py
+++ b/docs/scripts/configurations.py
@@ -19,9 +19,9 @@ _TAB_META_TEMPLATE = cleandoc(
      - *Width:* **{{width}}**
      - *Final Xor:* **0x{{final_xor:0{length}X}}**
      - *Init Value:* **0x{{init_value:0{length}X}}**
-     - *Rev Input:* **0x{{reverse_input:0{length}X}}**
+     - *Rev Input:* **{{reverse_input}}**
      - *Polynomial:* **0x{{polynomial:0{length}X}}**
-     - *Rev Output:* **0x{{reverse_output:0{length}X}}**
+     - *Rev Output:* **{{reverse_output}}**
 
     </div>
 """
diff --git a/src/crc/_crc.py b/src/crc/_crc.py
index 72c8779..653880f 100644
--- a/src/crc/_crc.py
+++ b/src/crc/_crc.py
@@ -481,7 +481,7 @@ class Crc8(enum.Enum):
 
 @enum.unique
 class Crc16(enum.Enum):
-    CCITT = Configuration(
+    XMODEM = Configuration(
         width=16,
         polynomial=0x1021,
         init_value=0x0000,
@@ -526,6 +526,15 @@ class Crc16(enum.Enum):
         reverse_output=False,
     )
 
+    KERMIT = Configuration(
+        width=16,
+        polynomial=0x1021,
+        init_value=0x0000,
+        final_xor_value=0x0000,
+        reverse_input=True,
+        reverse_output=True,
+    )
+
 
 @enum.unique
 class Crc32(enum.Enum):


Test patch:
diff --git a/test/unit/test_crc.py b/test/unit/test_crc.py
index bb42691..27fbd26 100644
--- a/test/unit/test_crc.py
+++ b/test/unit/test_crc.py
@@ -237,7 +237,7 @@ class RegisterTest(unittest.TestCase):
                 self.assertEqual(test.checksum, crc_register.digest())
 
     def test_crc16_ccitt(self):
-        config = Crc16.CCITT
+        config = Crc16.XMODEM
         for register_type in self._register_types:
             crc_register = register_type(config)
             test_suit = [
@@ -284,6 +284,22 @@ class RegisterTest(unittest.TestCase):
                 crc_register.update(test.data.encode("utf-8"))
                 self.assertEqual(test.checksum, crc_register.digest())
 
+    def test_cr16_kermit(self):
+        config = Crc16.KERMIT
+        for register_type in self._register_types:
+            crc_register = register_type(config)
+            test_suit = [
+                Fixture(data="", checksum=0x0000),
+                Fixture(data=string.digits[1:], checksum=0x2189),
+                Fixture(data=string.digits[1:][::-1], checksum=0x349F),
+                Fixture(data=string.digits, checksum=0x5F6E),
+                Fixture(data=string.digits[::-1], checksum=0x5DC9),
+            ]
+            for test in test_suit:
+                crc_register.init()
+                crc_register.update(test.data.encode("utf-8"))
+                self.assertEqual(test.checksum, crc_register.digest())
+
     def test_crc16_with_reflected_input(self):
         config = Configuration(16, 0x1021, 0, 0, True, False)
         for register_type in self._register_types: